Skip to content

Commit

Permalink
enhanced text cursor
Browse files Browse the repository at this point in the history
  • Loading branch information
victor-pogor committed Nov 19, 2024
1 parent 2b08521 commit 86ba750
Show file tree
Hide file tree
Showing 10 changed files with 433 additions and 355 deletions.
15 changes: 9 additions & 6 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@
"isRoot": true,
"tools": {
"dotnet-reportgenerator-globaltool": {
"version": "5.3.7",
"version": "5.3.11",
"commands": [
"reportgenerator"
]
],
"rollForward": false
},
"dotnet-config": {
"version": "1.0.6",
"version": "1.2.0",
"commands": [
"dotnet-config"
]
],
"rollForward": false
},
"dotnet-stryker": {
"version": "4.0.6",
"version": "4.3.0",
"commands": [
"dotnet-stryker"
]
],
"rollForward": false
}
}
}
18 changes: 9 additions & 9 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<Project>
<ItemGroup>
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="8.0.7" />
<PackageVersion Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.7" />
<PackageVersion Include="Microsoft.Extensions.ObjectPool" Version="8.0.7" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Localization" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Localization.Abstractions" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.ObjectPool" Version="9.0.0" />
</ItemGroup>
<!-- Analyzers -->
<ItemGroup>
<PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.17">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageVersion Include="SonarAnalyzer.CSharp" Version="9.30.0.95878">
<PackageVersion Include="SonarAnalyzer.CSharp" Version="9.32.0.97167">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageVersion Include="Roslynator.Analyzers" Version="4.12.4">
<PackageVersion Include="Roslynator.Analyzers" Version="4.12.9">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
Expand All @@ -26,8 +26,8 @@
</ItemGroup>
<!-- Test packages -->
<ItemGroup>
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageVersion Include="xunit" Version="2.9.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
Expand All @@ -36,7 +36,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageVersion>
<PackageVersion Include="NSubstitute" Version="5.1.0" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
</ItemGroup>
<!-- Benchmarking packages -->
<ItemGroup>
Expand Down
76 changes: 41 additions & 35 deletions src/OffDotNet.CodeAnalysis.Pdf/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@
"net8.0": {
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Direct",
"requested": "[8.0.1, )",
"resolved": "8.0.1",
"contentHash": "fGLiCRLMYd00JYpClraLjJTNKLmMJPnqxMaiRzEBIIvevlzxz33mXy39Lkd48hu1G+N21S7QpaO5ZzKsI6FRuA=="
"requested": "[9.0.0, )",
"resolved": "9.0.0",
"contentHash": "+6f2qv2a3dLwd5w6JanPIPs47CxRbnk+ZocMJUhv9NxP88VlOcJYZs9jY+MYSjxvady08bUZn6qgiNh7DadGgg=="
},
"Microsoft.Extensions.ObjectPool": {
"type": "Direct",
"requested": "[8.0.7, )",
"resolved": "8.0.7",
"contentHash": "2yLweyqmpuuFSRo+I3sLHMxmnAgNcI537kBJiyv49U2ZEqo00jZcG8lrnD8uCiOJp9IklYyTZULtbsXoFVzsjQ=="
"requested": "[9.0.0, )",
"resolved": "9.0.0",
"contentHash": "UbsU/gYe4nv1DeqMXIVzDfNNek7Sk2kKuAOXL/Y+sLcAR0HwFUqzg1EPiU88jeHNe0g81aPvvHbvHarQr3r9IA=="
},
"Roslynator.Analyzers": {
"type": "Direct",
"requested": "[4.12.4, )",
"resolved": "4.12.4",
"contentHash": "isl8hAh7yFNjyBEC4YlTSi+xGBblqBUC/2MCMmnBPwuXPewb7XYnMRzT3vXbP/gOGwT8hZUOy1g/aRH3lAF/NQ=="
"requested": "[4.12.9, )",
"resolved": "4.12.9",
"contentHash": "X6lDpN/D5wuinq37KIx+l3GSUe9No+8bCjGBTI5sEEtxapLztkHg6gzNVhMXpXw8P+/5gFYxTXJ5Pf8O4iNz/w=="
},
"SonarAnalyzer.CSharp": {
"type": "Direct",
"requested": "[9.30.0.95878, )",
"resolved": "9.30.0.95878",
"contentHash": "P0DylTJphECGE9HD6yho7rb6qs2WTTW36QUu5ezGRJeZpq8ItlRLmzUpxNHVOaudJywcnKO1DdRyZSaU7LXOcA=="
"requested": "[9.32.0.97167, )",
"resolved": "9.32.0.97167",
"contentHash": "Yxk86RV+8ynJpUhku1Yw2hITFmnmXKkXJ73cIFSy85ol5SnWREQg9RuTyV8nI7V7+pyLKpCfRmD7P0widsgjkg=="
},
"StyleCop.Analyzers": {
"type": "Direct",
Expand All @@ -37,57 +37,63 @@
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
"resolved": "8.0.1",
"contentHash": "RIFgaqoaINxkM2KTOw72dmilDmTrYA0ns2KW4lDz4gZ2+o6IQ894CzmdL3StM2oh7QQq44nCWiqKqc4qUI9Jmg==",
"resolved": "9.0.0",
"contentHash": "g0UfujELzlLbHoVG8kPKVBaW470Ewi+jnptGS9KUi6jcb+k2StujtK3m26DFSGGwQ/+bVgZfsWqNzlP6YOejvw==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.1"
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
"System.Diagnostics.DiagnosticSource": "9.0.0"
}
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "8.0.2",
"contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==",
"resolved": "9.0.0",
"contentHash": "y2146b3jrPI3Q0lokKXdKLpmXqakYbDIPDV6r3M8SqvSf45WwOTzkyfDpxnZXJsJQEpAsAqjUq5Pu8RCJMjubg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0",
"Microsoft.Extensions.Primitives": "8.0.0"
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
"Microsoft.Extensions.Primitives": "9.0.0"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g=="
"resolved": "9.0.0",
"contentHash": "N3qEBzmLMYiASUlKxxFIISP4AiwuPTHF5uCh+2CWSwwzAJiIYx0kBJsS30cp1nvhSySFAVi30jecD307jV+8Kg=="
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.556",
"contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ=="
},
"System.Diagnostics.DiagnosticSource": {
"type": "Transitive",
"resolved": "9.0.0",
"contentHash": "ddppcFpnbohLWdYKr/ZeLZHmmI+DXFgZ3Snq+/E7SwcdW4UnvxmaugkwGywvGVWkHPGCSZjCP+MLzu23AL5SDw=="
},
"offdotnet.codeanalysis": {
"type": "Project",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "[8.0.1, )",
"Microsoft.Extensions.Localization": "[8.0.7, )",
"Microsoft.Extensions.Localization.Abstractions": "[8.0.7, )",
"Microsoft.Extensions.ObjectPool": "[8.0.7, )"
"Microsoft.Extensions.DependencyInjection.Abstractions": "[9.0.0, )",
"Microsoft.Extensions.Localization": "[9.0.0, )",
"Microsoft.Extensions.Localization.Abstractions": "[9.0.0, )",
"Microsoft.Extensions.ObjectPool": "[9.0.0, )"
}
},
"Microsoft.Extensions.Localization": {
"type": "CentralTransitive",
"requested": "[8.0.7, )",
"resolved": "8.0.7",
"contentHash": "kdI24IfC1Jk3zfhWvYmuzvkzuKp+5Shjmfq0vk6EKBB+Udt4Gu1SkVSkMWJkYZFag+ndd+sTroUKDC/sud/DYQ==",
"requested": "[8.0.10, )",
"resolved": "9.0.0",
"contentHash": "Up8Juy8Bh+vL+fXmMWsoSg/G6rszmLFiF44aI2tpOMJE7Ln4D9s37YxOOm81am4Z+V7g8Am3AgVwHYJzi+cL/g==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.1",
"Microsoft.Extensions.Localization.Abstractions": "8.0.7",
"Microsoft.Extensions.Logging.Abstractions": "8.0.1",
"Microsoft.Extensions.Options": "8.0.2"
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0",
"Microsoft.Extensions.Localization.Abstractions": "9.0.0",
"Microsoft.Extensions.Logging.Abstractions": "9.0.0",
"Microsoft.Extensions.Options": "9.0.0"
}
},
"Microsoft.Extensions.Localization.Abstractions": {
"type": "CentralTransitive",
"requested": "[8.0.7, )",
"resolved": "8.0.7",
"contentHash": "uCsxqBBJEsSoV52tX/v+bxxN0e1O8WYIRR7tmcEmVVkRSX+0k4ZJcaL79ddus+0HIm3ssjV/dJk56XufDrGDqg=="
"requested": "[9.0.0, )",
"resolved": "9.0.0",
"contentHash": "wc7PaRhPOnio5Csj80b3UgBWA5l6bp28EhGem7gtfpVopcwbkfPb2Sk8Cu6eBnIW3ZNf1YUgYJzwtjzZEM8+iw=="
}
}
}
Expand Down
92 changes: 26 additions & 66 deletions src/OffDotNet.CodeAnalysis/Lexer/ITextCursor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,109 +7,69 @@ namespace OffDotNet.CodeAnalysis.Lexer;

using Utils;

/// <summary>Represents a text cursor for navigating and processing text data.</summary>
/// <example>
/// <code>
/// SLIDING position
/// WINDOW |
/// -------- + --------
/// | |
/// basis =======>> offset
/// | |
/// -------------------------------
/// SRC: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
/// -------------------------------
/// | |
/// basis ==>> offset
/// | |
/// ---- + ----
/// LEXEME |
/// SUB-WINDOW position
/// </code>
/// </example>
/// <inheritdoc cref="TextCursor"/>
public interface ITextCursor : IDisposable
{
/// <summary>Gets the source text.</summary>
/// <inheritdoc cref="TextCursor.SourceText"/>
ISourceText SourceText { get; }

/// <summary>
/// Gets the current byte at the cursor position.
/// </summary>
/// <inheritdoc cref="TextCursor.Current"/>
Option<byte> Current { get; }

/// <summary>
/// Gets a value indicating whether the cursor is at the end of the text.
/// </summary>
/// <inheritdoc cref="TextCursor.IsAtEnd"/>
bool IsAtEnd { get; }

/// <summary>Gets the start offset inside the window (relative to the <see cref="ISourceText"/> start).</summary>
/// <inheritdoc cref="TextCursor.WindowStart"/>
int WindowStart { get; }

/// <summary>Gets the end offset inside the window (relative to the <see cref="WindowStart"/>).</summary>
/// <inheritdoc cref="TextCursor.Offset"/>
int Offset { get; }

/// <summary>Gets the absolute position in the <see cref="ISourceText"/>.</summary>
/// <inheritdoc cref="TextCursor.Position"/>
int Position => WindowStart + Offset;

/// <summary>Gets a value indicating whether the window is in parsing lexeme mode.</summary>
/// <inheritdoc cref="TextCursor.LexemeStart"/>
bool IsLexemeMode { get; }

/// <summary>Gets the lexeme start offset relative to the <see cref="WindowStart">window start</see>.</summary>
/// <inheritdoc cref="TextCursor.LexemeStart"/>
int LexemeStart { get; }

/// <summary>Gets the absolute position of the lexeme in the <see cref="ISourceText"/>.</summary>
/// <inheritdoc cref="TextCursor.LexemePosition"/>
int LexemePosition => WindowStart + LexemeStart;

/// <summary>Gets the width of the lexeme.</summary>
/// <inheritdoc cref="TextCursor.LexemeWidth"/>
int LexemeWidth => Offset - LexemeStart;

/// <summary>Gets the text window.</summary>
/// <inheritdoc cref="TextCursor.Window"/>
ReadOnlyMemory<byte> Window { get; }

/// <summary>Gets the number of characters in the window.</summary>
/// <inheritdoc cref="TextCursor.WindowSize"/>
int WindowSize { get; }

/// <summary>
/// Peeks at the byte at the specified delta from the current position.
/// </summary>
/// <param name="delta">The delta from the current position.</param>
/// <returns>The byte at the specified delta if available; otherwise, <see cref="Option{T}.None"/>.</returns>
Option<byte> Peek(int delta = 0);

/// <summary>
/// Advances the cursor by the specified delta.
/// </summary>
/// <param name="delta">The delta by which to advance the cursor.</param>
/// <inheritdoc cref="TextCursor.Peek()"/>
Option<byte> Peek();

/// <inheritdoc cref="TextCursor.Peek(int)"/>
Option<byte> Peek(int delta);

/// <inheritdoc cref="TextCursor.Advance(int)"/>
void Advance(int delta = 1);

/// <summary>
/// Advances the cursor while the specified predicate is true.
/// </summary>
/// <param name="predicate">The predicate to test each byte against.</param>
/// <inheritdoc cref="TextCursor.Advance(Predicate{byte})"/>
void Advance(Predicate<byte> predicate);

/// <summary>
/// Tries to advance the cursor if the current byte matches the specified byte.
/// </summary>
/// <param name="b">The byte to match against.</param>
/// <returns>True if the cursor was advanced; otherwise, false.</returns>
/// <inheritdoc cref="TextCursor.TryAdvance(byte)"/>
bool TryAdvance(byte b);

/// <summary>
/// Tries to advance the cursor if the subsequent bytes match the specified subtext.
/// </summary>
/// <param name="subtext">The subtext to match against.</param>
/// <returns>True if the cursor was advanced; otherwise, false.</returns>
/// <inheritdoc cref="TextCursor.TryAdvance(ReadOnlySpan{byte})"/>
bool TryAdvance(ReadOnlySpan<byte> subtext);

/// <summary>Slides the text window to the specified start position and size.</summary>
/// <param name="windowStart">The start position of the window.</param>
/// <param name="windowSize">The size of the window.</param>
/// <inheritdoc cref="TextCursor.SlideTextWindow"/>
void SlideTextWindow(int windowStart = -1, int windowSize = -1);

/// <summary>Starts parsing a lexeme and sets the <see cref="LexemeStart"/> to the current <see cref="Offset"/> value.</summary>
/// <inheritdoc cref="TextCursor.StartLexemeMode"/>
public void StartLexemeMode();

/// <summary>Stops parsing a lexeme.</summary>
/// <inheritdoc cref="TextCursor.StopLexemeMode"/>
public void StopLexemeMode();
}
Loading

0 comments on commit 86ba750

Please sign in to comment.