From 38199307fc688839ccf69f1b7405e2d4109ed7cf Mon Sep 17 00:00:00 2001
From: Luthetus <45454132+huntercfreeman@users.noreply.github.com>
Date: Tue, 17 Dec 2024 17:16:15 -0500
Subject: [PATCH 2/8] Add button: Test rediscovery only happens once
---
.../Displays/TestExplorerDisplay.razor | 14 ++++++++++
.../Displays/TestExplorerDisplay.razor.cs | 6 ++++
.../States/TestExplorerState.Effector.cs | 28 ++++++++++++++++++-
.../Displays/StartupControlDisplay.razor | 2 +-
4 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/Displays/TestExplorerDisplay.razor b/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/Displays/TestExplorerDisplay.razor
index af7ca4872..1a2daf59a 100644
--- a/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/Displays/TestExplorerDisplay.razor
+++ b/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/Displays/TestExplorerDisplay.razor
@@ -49,6 +49,20 @@
+
+ @{
+ var iconDriver = new IconDriver(
+ AppOptionsStateWrap.Value.Options.IconSizeInPixels,
+ AppOptionsStateWrap.Value.Options.IconSizeInPixels);
+ }
+
+
+
Total: @(renderBatchValidated.TestExplorerState.TotalTestCount);
NotRan: @(renderBatchValidated.TestExplorerState.NotRanTestHashSet.Count);
Passed: @(renderBatchValidated.TestExplorerState.PassedTestHashSet.Count);
diff --git a/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/Displays/TestExplorerDisplay.razor.cs b/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/Displays/TestExplorerDisplay.razor.cs
index db44a3795..5f4b80762 100644
--- a/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/Displays/TestExplorerDisplay.razor.cs
+++ b/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/Displays/TestExplorerDisplay.razor.cs
@@ -53,6 +53,7 @@ protected override void OnInitialized()
base.OnInitialized();
}
+
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
@@ -136,4 +137,9 @@ private void RegisterDetailsTextEditor(TextEditorModel model)
return Task.CompletedTask;
});
}
+
+ private void DispatchShouldInitializeEffect()
+ {
+ Dispatcher.Dispatch(new TestExplorerState.ShouldInitializeEffect());
+ }
}
\ No newline at end of file
diff --git a/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/States/TestExplorerState.Effector.cs b/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/States/TestExplorerState.Effector.cs
index 0f0069d90..2d01c761b 100644
--- a/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/States/TestExplorerState.Effector.cs
+++ b/Source/Lib/Extensions/Extensions.DotNet/TestExplorers/States/TestExplorerState.Effector.cs
@@ -26,6 +26,28 @@ public Effector(
_dotNetSolutionStateWrap = dotNetSolutionStateWrap;
}
+ ///
+ /// Each time the user opens the 'Test Explorer' panel,
+ /// a check is done to see if the data being displayed
+ /// is in sync with the user's selected .NET solution.
+ ///
+ /// If it is not in sync, then it starts discovering tests for each of the
+ /// projects in the solution.
+ ///
+ /// But, if the user cancels this task, if they change panel tabs
+ /// from the 'Test Explorer' to something else, when they return
+ /// it will once again try to discover tests in all the projects for the solution.
+ ///
+ /// This is very annoying from a user perspective.
+ /// So this field will track whether we've already started
+ /// the task to discover tests in all the projects for the solution or not.
+ ///
+ /// This is fine because there is a button in the top left of the panel that
+ /// has a 'refresh' icon and it will start this task if the
+ /// user manually clicks it, (even if they cancelled the automatic invocation).
+ ///
+ private string _intentToDiscoverTestsInSolutionFilePath = string.Empty;
+
[EffectMethod(typeof(DotNetSolutionState.StateHasChanged))]
public Task HandleDotNetSolutionStateStateHasChanged(IDispatcher dispatcher)
{
@@ -46,8 +68,12 @@ public Task HandleUserInterfaceWasInitializedEffect(IDispatcher dispatcher)
var testExplorerState = _testExplorerStateWrap.Value;
- if (dotNetSolutionModel.AbsolutePath.Value != testExplorerState.SolutionFilePath)
+ if (dotNetSolutionModel.AbsolutePath.Value != testExplorerState.SolutionFilePath &&
+ _intentToDiscoverTestsInSolutionFilePath != dotNetSolutionModel.AbsolutePath.Value)
+ {
+ _intentToDiscoverTestsInSolutionFilePath = dotNetSolutionModel.AbsolutePath.Value;
dispatcher.Dispatch(new TestExplorerState.ShouldInitializeEffect());
+ }
return Task.CompletedTask;
}
diff --git a/Source/Lib/Ide/Ide.RazorLib/StartupControls/Displays/StartupControlDisplay.razor b/Source/Lib/Ide/Ide.RazorLib/StartupControls/Displays/StartupControlDisplay.razor
index c7545aa41..df059ae93 100644
--- a/Source/Lib/Ide/Ide.RazorLib/StartupControls/Displays/StartupControlDisplay.razor
+++ b/Source/Lib/Ide/Ide.RazorLib/StartupControls/Displays/StartupControlDisplay.razor
@@ -1,6 +1,6 @@
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
-@{
+@{
var localStartupControlState = StartupControlStateWrap.Value;
bool isExecuting;
From 2098328e246ce18eb0b58d14f93ee33c65b7a589 Mon Sep 17 00:00:00 2001
From: Luthetus <45454132+huntercfreeman@users.noreply.github.com>
Date: Wed, 18 Dec 2024 12:03:53 -0500
Subject: [PATCH 3/8] Parse array type definition
---
.../BinderCase/CSharpBinder.Expressions.cs | 8 +--
.../Syntax/Nodes/TypeClauseNode.cs | 1 +
.../Parsers/ExpressionAsStatementTests.cs | 49 ++++++++++++++++++-
3 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs b/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs
index 39183535c..2bb7e0a47 100644
--- a/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs
+++ b/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs
@@ -1321,9 +1321,11 @@ public IExpressionNode TypeClauseMergeToken(
}
goto default;
- case SyntaxKind.WithTokenContextualKeyword:
- Console.WriteLine("case SyntaxKind.WithTokenContextualKeyword)");
- goto default;
+ case SyntaxKind.OpenSquareBracketToken:
+ typeClauseNode.ArrayRank++;
+ return typeClauseNode;
+ case SyntaxKind.CloseSquareBracketToken:
+ return typeClauseNode;
default:
if (UtilityApi.IsConvertibleToIdentifierToken(token.SyntaxKind))
{
diff --git a/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/TypeClauseNode.cs b/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/TypeClauseNode.cs
index 5e75e3ebd..2cd50e75d 100644
--- a/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/TypeClauseNode.cs
+++ b/Source/Lib/TextEditor/CompilerServices/Syntax/Nodes/TypeClauseNode.cs
@@ -71,6 +71,7 @@ public TypeClauseNode(
TypeClauseNode IExpressionNode.ResultTypeClauseNode => TypeFacts.Pseudo.ToTypeClause();
public bool HasQuestionMark { get; set; }
+ public int ArrayRank { get; set; }
///
/// TODO: Change this attribute node property.
diff --git a/Source/Tests/CompilerServices/CSharp/SmokeTests/Parsers/ExpressionAsStatementTests.cs b/Source/Tests/CompilerServices/CSharp/SmokeTests/Parsers/ExpressionAsStatementTests.cs
index da95e9263..8a0894f59 100644
--- a/Source/Tests/CompilerServices/CSharp/SmokeTests/Parsers/ExpressionAsStatementTests.cs
+++ b/Source/Tests/CompilerServices/CSharp/SmokeTests/Parsers/ExpressionAsStatementTests.cs
@@ -1971,9 +1971,54 @@ public void VariableAssignmentExpressionNode()
}
[Fact]
- public void Array()
+ public void Array_Definition_RankOne()
{
- var test = new Test(@"return someList[0];");
+ var test = new Test(@"int[] someList;");
+ var topCodeBlock = test.CompilationUnit.RootCodeBlockNode;
+ WriteChildrenIndentedRecursive(topCodeBlock, nameof(topCodeBlock));
+ var variableDeclarationNode = (VariableDeclarationNode)topCodeBlock.GetChildList().Single();
+ Assert.Equal(SyntaxKind.VariableDeclarationNode, variableDeclarationNode.SyntaxKind);
+ Assert.Equal(1, variableDeclarationNode.TypeClauseNode.ArrayRank);
+ }
+
+ [Fact]
+ public void Array_Definition_RankTwo()
+ {
+ var test = new Test(@"int[][] someList;");
+ var topCodeBlock = test.CompilationUnit.RootCodeBlockNode;
+ WriteChildrenIndentedRecursive(topCodeBlock, nameof(topCodeBlock));
+ var variableDeclarationNode = (VariableDeclarationNode)topCodeBlock.GetChildList().Single();
+ Assert.Equal(SyntaxKind.VariableDeclarationNode, variableDeclarationNode.SyntaxKind);
+ Assert.Equal(2, variableDeclarationNode.TypeClauseNode.ArrayRank);
+ }
+
+ [Fact]
+ public void Array_Definition_Nullable()
+ {
+ var test = new Test(@"int[]? someList;");
+ var topCodeBlock = test.CompilationUnit.RootCodeBlockNode;
+ WriteChildrenIndentedRecursive(topCodeBlock, nameof(topCodeBlock));
+ var variableDeclarationNode = (VariableDeclarationNode)topCodeBlock.GetChildList().Single();
+ Assert.Equal(SyntaxKind.VariableDeclarationNode, variableDeclarationNode.SyntaxKind);
+ Assert.Equal(1, variableDeclarationNode.TypeClauseNode.ArrayRank);
+ Assert.True(variableDeclarationNode.TypeClauseNode.HasQuestionMark);
+ }
+
+ [Fact]
+ public void Array_Assignment()
+ {
+ var test = new Test(@"someList = new int[1];");
+ var topCodeBlock = test.CompilationUnit.RootCodeBlockNode;
+ WriteChildrenIndentedRecursive(topCodeBlock, nameof(topCodeBlock));
+ var returnStatementNode = (ReturnStatementNode)topCodeBlock.GetChildList().Single();
+ Assert.Equal(SyntaxKind.ReturnStatementNode, returnStatementNode.SyntaxKind);
+
+ }
+
+ [Fact]
+ public void Array_Access()
+ {
+ var test = new Test(@"someList[0];");
var topCodeBlock = test.CompilationUnit.RootCodeBlockNode;
WriteChildrenIndentedRecursive(topCodeBlock, nameof(topCodeBlock));
var returnStatementNode = (ReturnStatementNode)topCodeBlock.GetChildList().Single();
From 5cc431e018fe7cc25a42ef09ea736a3d91037756 Mon Sep 17 00:00:00 2001
From: Luthetus <45454132+huntercfreeman@users.noreply.github.com>
Date: Wed, 18 Dec 2024 12:19:24 -0500
Subject: [PATCH 4/8] Show array in type clause node tooltip
---
.../Internals/Symbols/TypeSyntaxDisplay.razor | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Source/Lib/TextEditor/TextEditors/Displays/Internals/Symbols/TypeSyntaxDisplay.razor b/Source/Lib/TextEditor/TextEditors/Displays/Internals/Symbols/TypeSyntaxDisplay.razor
index 95226c552..c07229049 100644
--- a/Source/Lib/TextEditor/TextEditors/Displays/Internals/Symbols/TypeSyntaxDisplay.razor
+++ b/Source/Lib/TextEditor/TextEditors/Displays/Internals/Symbols/TypeSyntaxDisplay.razor
@@ -14,6 +14,7 @@
GenericArgumentsListingNode? genericArgumentsListingNode;
GenericParametersListingNode? genericParametersListingNode;
bool? hasQuestionMark;
+ int arrayRank;
if (syntaxViewModelLocal.DefinitionNode is null && syntaxViewModelLocal.TargetNode is null && syntaxViewModelLocal.TargetSymbol is null)
{
@@ -24,6 +25,7 @@
genericArgumentsListingNode = null;
genericParametersListingNode = null;
hasQuestionMark = null;
+ arrayRank = 0;
}
else if (syntaxViewModelLocal.DefinitionNode is not null && syntaxViewModelLocal.DefinitionNode.SyntaxKind == SyntaxKind.TypeDefinitionNode)
{
@@ -41,6 +43,7 @@
genericArgumentsListingNode = typeDefinitionNode.GenericArgumentsListingNode;
genericParametersListingNode = null;
hasQuestionMark = null;
+ arrayRank = 0;
}
else if (syntaxViewModelLocal.TargetNode is not null && syntaxViewModelLocal.TargetNode.SyntaxKind == SyntaxKind.TypeClauseNode)
{
@@ -58,6 +61,7 @@
genericArgumentsListingNode = null;
genericParametersListingNode = typeClauseNode.GenericParametersListingNode;
hasQuestionMark = typeClauseNode.HasQuestionMark;
+ arrayRank = typeClauseNode.ArrayRank;
}
else if (syntaxViewModelLocal.TargetSymbol is not null && syntaxViewModelLocal.TargetSymbol.SyntaxKind == SyntaxKind.TypeSymbol)
{
@@ -68,6 +72,7 @@
genericArgumentsListingNode = null;
genericParametersListingNode = null;
hasQuestionMark = null;
+ arrayRank = 0;
}
else
{
@@ -78,6 +83,7 @@
genericArgumentsListingNode = null;
genericParametersListingNode = null;
hasQuestionMark = null;
+ arrayRank = 0;
}
}
@@ -125,4 +131,12 @@
{
?
}
+
+ @if (arrayRank > 0)
+ {
+ for (int badIndex = 0; badIndex < arrayRank; badIndex++)
+ {
+ []
+ }
+ }
From 89b72033041135a1846df6c07161d2776fd931f1 Mon Sep 17 00:00:00 2001
From: Luthetus <45454132+huntercfreeman@users.noreply.github.com>
Date: Wed, 18 Dec 2024 12:26:30 -0500
Subject: [PATCH 5/8] Skip over BangToken without causing a BadExpressionNode
---
.../CSharp/BinderCase/CSharpBinder.Expressions.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs b/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs
index 2bb7e0a47..fcb011589 100644
--- a/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs
+++ b/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs
@@ -847,6 +847,8 @@ public IExpressionNode EmptyMergeToken(
var returnStatementNode = new ReturnStatementNode((KeywordToken)token, EmptyExpressionNode.Empty);
parserModel.ExpressionList.Add((SyntaxKind.EndOfFileToken, returnStatementNode));
return EmptyExpressionNode.Empty;
+ case SyntaxKind.BangToken:
+ return emptyExpressionNode;
default:
return new BadExpressionNode(CSharpFacts.Types.Void.ToTypeClause(), emptyExpressionNode, token);
}
From e85d82236d331b41a25ce2b006358b98651c1346 Mon Sep 17 00:00:00 2001
From: Luthetus <45454132+huntercfreeman@users.noreply.github.com>
Date: Wed, 18 Dec 2024 12:44:22 -0500
Subject: [PATCH 6/8] Lex Pipe, PipePipe, Ampersand, AmpersandAmpersand
---
.../CSharp/LexerCase/CSharpLexer.cs | 34 +++++++++++
.../CompilerServices/Syntax/SyntaxKind.cs | 4 ++
.../Syntax/Tokens/AmpersandAmpersandToken.cs | 17 ++++++
.../Syntax/Tokens/AmpersandToken.cs | 17 ++++++
.../Syntax/Tokens/PipePipeToken.cs | 17 ++++++
.../Syntax/Tokens/PipeToken.cs | 17 ++++++
.../CSharp/SmokeTests/Lexers/LexerTests.cs | 56 +++++++++++++++++++
7 files changed, 162 insertions(+)
create mode 100644 Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/AmpersandAmpersandToken.cs
create mode 100644 Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/AmpersandToken.cs
create mode 100644 Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/PipePipeToken.cs
create mode 100644 Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/PipeToken.cs
diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs
index ea3168f8c..d4d58d498 100644
--- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs
+++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs
@@ -167,6 +167,40 @@ public static CSharpLexerOutput Lex(ResourceUri resourceUri, string sourceText)
lexerOutput.SyntaxTokenList.Add(new QuestionMarkToken(textSpan));
}
break;
+ case '|':
+ if (stringWalker.PeekCharacter(1) == '|')
+ {
+ var entryPositionIndex = stringWalker.PositionIndex;
+ stringWalker.ReadCharacter();
+ stringWalker.ReadCharacter();
+ var textSpan = new TextEditorTextSpan(entryPositionIndex, stringWalker.PositionIndex, (byte)GenericDecorationKind.None, stringWalker.ResourceUri, stringWalker.SourceText);
+ lexerOutput.SyntaxTokenList.Add(new PipePipeToken(textSpan));
+ }
+ else
+ {
+ var entryPositionIndex = stringWalker.PositionIndex;
+ stringWalker.ReadCharacter();
+ var textSpan = new TextEditorTextSpan(entryPositionIndex, stringWalker.PositionIndex, (byte)GenericDecorationKind.None, stringWalker.ResourceUri, stringWalker.SourceText);
+ lexerOutput.SyntaxTokenList.Add(new PipeToken(textSpan));
+ }
+ break;
+ case '&':
+ if (stringWalker.PeekCharacter(1) == '&')
+ {
+ var entryPositionIndex = stringWalker.PositionIndex;
+ stringWalker.ReadCharacter();
+ stringWalker.ReadCharacter();
+ var textSpan = new TextEditorTextSpan(entryPositionIndex, stringWalker.PositionIndex, (byte)GenericDecorationKind.None, stringWalker.ResourceUri, stringWalker.SourceText);
+ lexerOutput.SyntaxTokenList.Add(new AmpersandAmpersandToken(textSpan));
+ }
+ else
+ {
+ var entryPositionIndex = stringWalker.PositionIndex;
+ stringWalker.ReadCharacter();
+ var textSpan = new TextEditorTextSpan(entryPositionIndex, stringWalker.PositionIndex, (byte)GenericDecorationKind.None, stringWalker.ResourceUri, stringWalker.SourceText);
+ lexerOutput.SyntaxTokenList.Add(new AmpersandToken(textSpan));
+ }
+ break;
case '*':
{
var entryPositionIndex = stringWalker.PositionIndex;
diff --git a/Source/Lib/TextEditor/CompilerServices/Syntax/SyntaxKind.cs b/Source/Lib/TextEditor/CompilerServices/Syntax/SyntaxKind.cs
index 2308fca7e..13bca3be3 100644
--- a/Source/Lib/TextEditor/CompilerServices/Syntax/SyntaxKind.cs
+++ b/Source/Lib/TextEditor/CompilerServices/Syntax/SyntaxKind.cs
@@ -28,6 +28,10 @@ public enum SyntaxKind
EqualsEqualsToken,
QuestionMarkToken,
QuestionMarkQuestionMarkToken,
+ PipeToken,
+ PipePipeToken,
+ AmpersandToken,
+ AmpersandAmpersandToken,
BangToken,
StatementDelimiterToken,
ArraySyntaxToken,
diff --git a/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/AmpersandAmpersandToken.cs b/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/AmpersandAmpersandToken.cs
new file mode 100644
index 000000000..6521c9dd5
--- /dev/null
+++ b/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/AmpersandAmpersandToken.cs
@@ -0,0 +1,17 @@
+using Luthetus.TextEditor.RazorLib.Lexers.Models;
+
+namespace Luthetus.TextEditor.RazorLib.CompilerServices.Syntax.Tokens;
+
+public struct AmpersandAmpersandToken : ISyntaxToken
+{
+ public AmpersandAmpersandToken(TextEditorTextSpan textSpan)
+ {
+ ConstructorWasInvoked = true;
+ TextSpan = textSpan;
+ }
+
+ public TextEditorTextSpan TextSpan { get; }
+ public SyntaxKind SyntaxKind => SyntaxKind.AmpersandAmpersandToken;
+ public bool IsFabricated { get; init; }
+ public bool ConstructorWasInvoked { get; }
+}
diff --git a/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/AmpersandToken.cs b/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/AmpersandToken.cs
new file mode 100644
index 000000000..786b9890a
--- /dev/null
+++ b/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/AmpersandToken.cs
@@ -0,0 +1,17 @@
+using Luthetus.TextEditor.RazorLib.Lexers.Models;
+
+namespace Luthetus.TextEditor.RazorLib.CompilerServices.Syntax.Tokens;
+
+public struct AmpersandToken : ISyntaxToken
+{
+ public AmpersandToken(TextEditorTextSpan textSpan)
+ {
+ ConstructorWasInvoked = true;
+ TextSpan = textSpan;
+ }
+
+ public TextEditorTextSpan TextSpan { get; }
+ public SyntaxKind SyntaxKind => SyntaxKind.AmpersandToken;
+ public bool IsFabricated { get; init; }
+ public bool ConstructorWasInvoked { get; }
+}
\ No newline at end of file
diff --git a/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/PipePipeToken.cs b/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/PipePipeToken.cs
new file mode 100644
index 000000000..0e3d38de6
--- /dev/null
+++ b/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/PipePipeToken.cs
@@ -0,0 +1,17 @@
+using Luthetus.TextEditor.RazorLib.Lexers.Models;
+
+namespace Luthetus.TextEditor.RazorLib.CompilerServices.Syntax.Tokens;
+
+public struct PipePipeToken : ISyntaxToken
+{
+ public PipePipeToken(TextEditorTextSpan textSpan)
+ {
+ ConstructorWasInvoked = true;
+ TextSpan = textSpan;
+ }
+
+ public TextEditorTextSpan TextSpan { get; }
+ public SyntaxKind SyntaxKind => SyntaxKind.PipePipeToken;
+ public bool IsFabricated { get; init; }
+ public bool ConstructorWasInvoked { get; }
+}
\ No newline at end of file
diff --git a/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/PipeToken.cs b/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/PipeToken.cs
new file mode 100644
index 000000000..18703de49
--- /dev/null
+++ b/Source/Lib/TextEditor/CompilerServices/Syntax/Tokens/PipeToken.cs
@@ -0,0 +1,17 @@
+using Luthetus.TextEditor.RazorLib.Lexers.Models;
+
+namespace Luthetus.TextEditor.RazorLib.CompilerServices.Syntax.Tokens;
+
+public struct PipeToken : ISyntaxToken
+{
+ public PipeToken(TextEditorTextSpan textSpan)
+ {
+ ConstructorWasInvoked = true;
+ TextSpan = textSpan;
+ }
+
+ public TextEditorTextSpan TextSpan { get; }
+ public SyntaxKind SyntaxKind => SyntaxKind.PipeToken;
+ public bool IsFabricated { get; init; }
+ public bool ConstructorWasInvoked { get; }
+}
\ 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 244d53bb7..729fa6922 100644
--- a/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs
+++ b/Source/Tests/CompilerServices/CSharp/SmokeTests/Lexers/LexerTests.cs
@@ -136,6 +136,62 @@ public void LEX_BadToken()
throw new NotImplementedException();
}
+ [Fact]
+ public void LEX_PipeToken()
+ {
+ var resourceUri = new ResourceUri("UnitTests");
+ var sourceText = "|";
+ var lexerOutput = CSharpLexer.Lex(resourceUri, sourceText);
+
+ Assert.Equal(2, lexerOutput.SyntaxTokenList.Count);
+ var pipeToken = (PipeToken)lexerOutput.SyntaxTokenList[0];
+ var endOfFileToken = (EndOfFileToken)lexerOutput.SyntaxTokenList[1];
+
+ Assert.Equal(SyntaxKind.PipeToken, pipeToken.SyntaxKind);
+ }
+
+ [Fact]
+ public void LEX_PipePipeToken()
+ {
+ var resourceUri = new ResourceUri("UnitTests");
+ var sourceText = "||";
+ var lexerOutput = CSharpLexer.Lex(resourceUri, sourceText);
+
+ Assert.Equal(2, lexerOutput.SyntaxTokenList.Count);
+ var pipePipeToken = (PipePipeToken)lexerOutput.SyntaxTokenList[0];
+ var endOfFileToken = (EndOfFileToken)lexerOutput.SyntaxTokenList[1];
+
+ Assert.Equal(SyntaxKind.PipePipeToken, pipePipeToken.SyntaxKind);
+ }
+
+ [Fact]
+ public void LEX_AmpersandToken()
+ {
+ var resourceUri = new ResourceUri("UnitTests");
+ var sourceText = "&";
+ var lexerOutput = CSharpLexer.Lex(resourceUri, sourceText);
+
+ Assert.Equal(2, lexerOutput.SyntaxTokenList.Count);
+ var ampersandToken = (AmpersandToken)lexerOutput.SyntaxTokenList[0];
+ var endOfFileToken = (EndOfFileToken)lexerOutput.SyntaxTokenList[1];
+
+ Assert.Equal(SyntaxKind.AmpersandToken, ampersandToken.SyntaxKind);
+ }
+
+ [Fact]
+ public void LEX_AmpersandAmpersandToken()
+ {
+ var resourceUri = new ResourceUri("UnitTests");
+ var sourceText = "&&";
+ var lexerOutput = CSharpLexer.Lex(resourceUri, sourceText);
+
+ Assert.Equal(2, lexerOutput.SyntaxTokenList.Count);
+ var ampersandAmpersandToken = (AmpersandAmpersandToken)lexerOutput.SyntaxTokenList[0];
+ var endOfFileToken = (EndOfFileToken)lexerOutput.SyntaxTokenList[1];
+
+ Assert.Equal(SyntaxKind.AmpersandAmpersandToken, ampersandAmpersandToken.SyntaxKind);
+ }
+
[Fact]
public void LEX_BangToken()
{
From 71fa5ead7d053ce24763e7ceecfe2df708021a95 Mon Sep 17 00:00:00 2001
From: Luthetus <45454132+huntercfreeman@users.noreply.github.com>
Date: Wed, 18 Dec 2024 13:36:54 -0500
Subject: [PATCH 7/8] --luth_te_preprocessor-directive-foreground-color
---
.../CSharp/BinderCase/CSharpBinder.Expressions.cs | 6 ++++++
.../CSharp/LexerCase/CSharpLexer.cs | 13 +++++++++++--
.../Decoration/GenericDecorationMapper.cs | 2 +-
.../Lib/TextEditor/wwwroot/luthetusTextEditor.css | 8 ++++++++
4 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs b/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs
index fcb011589..1036d1990 100644
--- a/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs
+++ b/Source/Lib/CompilerServices/CSharp/BinderCase/CSharpBinder.Expressions.cs
@@ -848,6 +848,12 @@ public IExpressionNode EmptyMergeToken(
parserModel.ExpressionList.Add((SyntaxKind.EndOfFileToken, returnStatementNode));
return EmptyExpressionNode.Empty;
case SyntaxKind.BangToken:
+ case SyntaxKind.PipeToken:
+ case SyntaxKind.PipePipeToken:
+ case SyntaxKind.AmpersandToken:
+ case SyntaxKind.AmpersandAmpersandToken:
+ case SyntaxKind.PlusPlusToken:
+ case SyntaxKind.MinusMinusToken:
return emptyExpressionNode;
default:
return new BadExpressionNode(CSharpFacts.Types.Void.ToTypeClause(), emptyExpressionNode, token);
diff --git a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs
index d4d58d498..c383b3ae0 100644
--- a/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs
+++ b/Source/Lib/CompilerServices/CSharp/LexerCase/CSharpLexer.cs
@@ -941,6 +941,7 @@ public static void LexPreprocessorDirectiveToken(ref CSharpLexerOutput lexerOutp
// Declare outside the while loop to avoid overhead of redeclaring each loop? not sure
var isNewLineCharacter = false;
+ var firstWhitespaceCharacterPositionIndex = -1;
while (!stringWalker.IsEof)
{
@@ -950,6 +951,11 @@ public static void LexPreprocessorDirectiveToken(ref CSharpLexerOutput lexerOutp
case '\n':
isNewLineCharacter = true;
break;
+ case '\t':
+ case ' ':
+ if (firstWhitespaceCharacterPositionIndex == -1)
+ firstWhitespaceCharacterPositionIndex = stringWalker.PositionIndex;
+ break;
default:
break;
}
@@ -959,11 +965,14 @@ public static void LexPreprocessorDirectiveToken(ref CSharpLexerOutput lexerOutp
_ = stringWalker.ReadCharacter();
}
+
+ if (firstWhitespaceCharacterPositionIndex == -1)
+ firstWhitespaceCharacterPositionIndex = stringWalker.PositionIndex;
var textSpan = new TextEditorTextSpan(
entryPositionIndex,
- stringWalker.PositionIndex,
- (byte)GenericDecorationKind.None,
+ firstWhitespaceCharacterPositionIndex,
+ (byte)GenericDecorationKind.PreprocessorDirective,
stringWalker.ResourceUri,
stringWalker.SourceText);
diff --git a/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationMapper.cs b/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationMapper.cs
index 87a10ad82..d4a4bd255 100644
--- a/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationMapper.cs
+++ b/Source/Lib/TextEditor/CompilerServices/GenericLexer/Decoration/GenericDecorationMapper.cs
@@ -20,7 +20,7 @@ public string Map(byte decorationByte)
GenericDecorationKind.CommentSingleLine => "luth_te_comment",
GenericDecorationKind.CommentMultiLine => "luth_te_comment",
GenericDecorationKind.Function => "luth_te_method",
- GenericDecorationKind.PreprocessorDirective => "luth_te_keyword",
+ GenericDecorationKind.PreprocessorDirective => "luth_te_preprocessor-directive",
GenericDecorationKind.DeliminationExtended => "luth_te_string-literal",
GenericDecorationKind.Type => "luth_te_type",
_ => string.Empty,
diff --git a/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css b/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css
index 5ea3e8b41..7b11e0aea 100644
--- a/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css
+++ b/Source/Lib/TextEditor/wwwroot/luthetusTextEditor.css
@@ -63,6 +63,10 @@
color: var(--luth_te_keyword-control-foreground-color);
}
+.luth_te_preprocessor-directive {
+ color: var(--luth_te_preprocessor-directive-foreground-color);
+}
+
.luth_te_comment {
color: var(--luth_te_comment-foreground-color);
}
@@ -542,6 +546,7 @@
--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_preprocessor-directive-foreground-color: rgb(143, 8, 196);
--luth_te_comment-foreground-color: rgb(0, 128, 0);
--luth_te_tag-name-foreground-color: rgb(128, 0, 0);
--luth_te_injected-language-fragment-color: rgb(225, 80, 220);
@@ -628,6 +633,7 @@
--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_preprocessor-directive-foreground-color: rgb(197, 134, 192);
--luth_te_comment-foreground-color: rgb(106, 153, 85);
--luth_te_tag-name-foreground-color: rgb(86, 156, 214);
--luth_te_injected-language-fragment-color: rgb(197, 134, 192);
@@ -714,6 +720,7 @@
--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_preprocessor-directive-foreground-color: rgb(215, 100, 100);
--luth_te_comment-foreground-color: rgb(142, 142, 142);
--luth_te_tag-name-foreground-color: var(--luth_te_keyword-foreground-color);
--luth_te_injected-language-fragment-color: rgb(215, 107, 179);
@@ -800,6 +807,7 @@
--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_preprocessor-directive-foreground-color: rgb(215,0,0);
--luth_te_comment-foreground-color: rgb(120, 120, 120);
--luth_te_tag-name-foreground-color: var(--luth_te_keyword-foreground-color);
--luth_te_injected-language-fragment-color: rgb(200, 0, 200);
From 8aa5744625c258df58bff7b2df043f5a69417048 Mon Sep 17 00:00:00 2001
From: Luthetus <45454132+huntercfreeman@users.noreply.github.com>
Date: Wed, 18 Dec 2024 14:07:03 -0500
Subject: [PATCH 8/8] v0.9.7.10
---
.../Ide.RazorLib/Luthetus.Ide.RazorLib.csproj | 2 +-
.../Displays/Internals/IdeInfoDisplay.razor | 28 ++++++++++++++++---
2 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/Source/Lib/Ide/Ide.RazorLib/Luthetus.Ide.RazorLib.csproj b/Source/Lib/Ide/Ide.RazorLib/Luthetus.Ide.RazorLib.csproj
index 181784a2b..84fbf8cf7 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.9
+ 0.9.7.10
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 42ef1de0e..fcc354850 100644
--- a/Source/Lib/Ide/Ide.RazorLib/Shareds/Displays/Internals/IdeInfoDisplay.razor
+++ b/Source/Lib/Ide/Ide.RazorLib/Shareds/Displays/Internals/IdeInfoDisplay.razor
@@ -172,16 +172,36 @@
Recent Changes:
-
v 0.9.7.9 (WIP_DATE)
+
v 0.9.7.10 (2024-12-18)
-
- Fix: 'this' keyword in function arguments listing.
+ Lex preprocessor directive
-
- Fix: primary constructor syntax.
+ Lex Pipe, PipePipe, Ampersand, AmpersandAmpersand
+
+ -
+ Skip over BangToken without causing a BadExpressionNode
+
+ -
+ Show array in type clause node tooltip
+
+ -
+ Parse array type definition
+
+ -
+ Add button: Test rediscovery only happens once
+
+
+
+
v 0.9.7.9 (2024-12-17)
+
-
- WIP_DESCRIPTION
+ Fix: 'this' keyword in function arguments listing.
+
+ -
+ Fix: primary constructor syntax.