Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formater rewrite. #400

Open
wants to merge 77 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 62 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
68065d6
Just collapible values for now.
Kuinox Feb 26, 2024
ff63e2a
wip
Kuinox Mar 6, 2024
fc28095
wip.
Kuinox Mar 8, 2024
1c475b1
Simple test case pass.
Kuinox Mar 10, 2024
6be2c8c
wip
Kuinox Mar 12, 2024
bef4be7
wip
Kuinox Mar 16, 2024
8189446
wip
Kuinox Mar 18, 2024
e582157
More progress
Kuinox Mar 23, 2024
c29882a
wip
Kuinox Mar 24, 2024
e51f56b
One more test green.
Kuinox Mar 31, 2024
61a1dbe
More tests are passing.
Kuinox Apr 6, 2024
dba4b22
Time for bulldozing.
Kuinox Apr 10, 2024
4dbcc9e
Some buldozing.
Kuinox Apr 13, 2024
e5f1661
rebuldozer
Kuinox Apr 21, 2024
6987857
re - re buldozing
Kuinox Apr 21, 2024
9326cd7
should i buldozer further ?
Kuinox Apr 22, 2024
6a9c830
I drunk too much for not committing before coding.
Kuinox Apr 26, 2024
cca9727
wip
Kuinox Apr 26, 2024
2495a41
All tests pass. Now need more tests.
Kuinox Apr 27, 2024
41b4254
wip.
Kuinox Apr 28, 2024
cec80c5
wip.
Kuinox Apr 29, 2024
cfc2f20
A bugfix.
Kuinox Apr 29, 2024
eef1ff0
Simplest comment case handled.
Kuinox Apr 29, 2024
9b4edb6
Added comments support.
Kuinox Apr 29, 2024
c43c83b
Removed CollapsableInt.
Kuinox Apr 30, 2024
5cdb31c
Remove dead code.
Kuinox Apr 30, 2024
a62d233
Cleanup
Kuinox Apr 30, 2024
f5f9436
Added failing test case.
Kuinox Apr 30, 2024
75e2cad
Fixed more edge case, added test for another one.
Kuinox May 1, 2024
d3961b8
Added more edgecases, more cleanup.
Kuinox May 2, 2024
e352977
Moar renames.
Kuinox May 2, 2024
2c698a7
PR feedback.
Kuinox May 2, 2024
845a611
Improved code readability.
Kuinox May 2, 2024
02de0ec
Improving readability.
Kuinox May 3, 2024
1a88e83
DRY FTW.
Kuinox May 3, 2024
80ec52b
Stop exposing the token reference in the metadata.
Kuinox May 3, 2024
58d9fd6
Removed token override.
Kuinox May 3, 2024
56f75b9
Factorized out formatter.
Kuinox May 3, 2024
82d72a9
Make the formatter core extensible.
Kuinox May 3, 2024
d6cde88
Factored out more non-draco specific code.
Kuinox May 4, 2024
286ba34
nullfix
Kuinox May 4, 2024
7f1f1ab
More code goes away ~
Kuinox May 4, 2024
de3ad18
Some regression.
Kuinox May 6, 2024
61262f0
a c# formatter.
Kuinox May 6, 2024
a97eb4f
Put formatter engine in a dedicated project.
Kuinox May 6, 2024
6d3f5e0
Conforming to repo syntax.
Kuinox May 6, 2024
8c17604
Some debug tooling.
Kuinox May 6, 2024
b611f56
Remove OnDifferent.
Kuinox May 6, 2024
5e589d6
bugfix
Kuinox May 6, 2024
fb40b8b
Bug fixed.
Kuinox May 6, 2024
edb4c97
Cleaned using.
Kuinox May 6, 2024
2216605
Added line return.
Kuinox May 6, 2024
4072e3b
Some PR feedback.
Kuinox May 6, 2024
70f94bf
More PR feedback.
Kuinox May 6, 2024
7dc3e8b
And more.
Kuinox May 6, 2024
46ab610
Remove empty formatter config.
Kuinox May 7, 2024
4b9256f
PR feedback.
Kuinox May 7, 2024
54dfffd
Remove force right pad.
Kuinox May 7, 2024
ed54478
wip.
Kuinox May 7, 2024
1dbbe1e
wip
Kuinox May 7, 2024
f1854a0
Removed Data property on scope infos.
Kuinox May 8, 2024
c59fe6a
More C# formatter progress.
Kuinox May 8, 2024
229962d
Created CSharpFormatterSettings plus a Draco specific settings.
Kuinox May 11, 2024
6cd5964
Fixed some PR feedback.
Kuinox May 12, 2024
175d0a8
Don't merge tokens that can fuse together.
Kuinox May 13, 2024
e3a33ce
Improved C# formatter.
Kuinox May 14, 2024
20dc27b
ohno
Kuinox May 14, 2024
4b30c73
Update src/Draco.FormatterEngine/Scope.cs
Kuinox Jun 2, 2024
57c6da8
Update src/Draco.Formatter.Csharp/CSharpFormatter.cs
Kuinox Jun 2, 2024
694eeb1
Dropped box to use a future instead.
Kuinox Jun 2, 2024
4199b12
Some improvements & pr feedback.
Kuinox Jul 21, 2024
d0f5c95
Forgot to commit this file.
Kuinox Jul 21, 2024
e6d5100
Deleted csharp formatter.
Kuinox Jul 29, 2024
8143fff
Some code simplifications.
Kuinox Jul 29, 2024
311a53e
Merge remote-tracking branch 'origin/main' into feature/formater_rework
Kuinox Aug 3, 2024
14aab95
VS did open it fine...
Kuinox Aug 3, 2024
b702b49
Some fixes of the code simplification.
Kuinox Aug 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/Draco.Compiler.Benchmarks/E2eBenchmarks.cs
Kuinox marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ public class E2eBenchmarks : FolderBenchmarkBase
{
private MemoryStream peStream = null!;

public E2eBenchmarks()
: base("e2e")
public E2eBenchmarks() : base("e2e")
{
}

Expand Down
2 changes: 1 addition & 1 deletion src/Draco.Compiler.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ private static void FormatCommand(FileInfo input, FileInfo? output)
{
var syntaxTree = GetSyntaxTrees(input).First();
using var outputStream = OpenOutputOrStdout(output);
new StreamWriter(outputStream).Write(syntaxTree.Format().ToString());
new StreamWriter(outputStream).Write(syntaxTree.Format());
}

private static ImmutableArray<SyntaxTree> GetSyntaxTrees(params FileInfo[] input)
Expand Down
244 changes: 238 additions & 6 deletions src/Draco.Compiler.Tests/Syntax/ParseTreeFormatterTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using Draco.Compiler.Api.Syntax;
using Xunit.Abstractions;

namespace Draco.Compiler.Tests.Syntax;

public sealed class SyntaxTreeFormatterTests
public sealed class SyntaxTreeFormatterTests(ITestOutputHelper logger)
{
[Fact]
public void TestFormatting()
public void SomeCodeSampleShouldBeFormattedCorrectly()
{
var input = """"
func main ( ) {
Expand All @@ -17,6 +18,7 @@ func main ( ) {
val singleLineString = "" ;
var multilineString = #"""
something
test
"""# ;
val y
= 4-2
Expand Down Expand Up @@ -58,6 +60,7 @@ func main() {
val singleLineString = "";
var multilineString = #"""
something
test
"""#;
val y = 4 - 2 mod 4 + 3;
while (true) {
Expand Down Expand Up @@ -89,12 +92,12 @@ func main() {

"""";

var actual = SyntaxTree.Parse(input).Format().ToString();
var actual = SyntaxTree.Parse(input).Format();
Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
}

[Fact]
public void TestFormattingInlineMethod()
public void InlineMethodShouldBeFormattedCorrectly()
{
var input = """
import System.Console;
Expand All @@ -109,14 +112,243 @@ func main() {
var expected = """
import System.Console;

func max(a:int32, b:int32): int32 = if (a > b) a else b;
func max(a: int32, b: int32): int32 = if (a > b) a else b;

func main() {
WriteLine(max(12, 34));
}

""";
var actual = SyntaxTree.Parse(input).Format().ToString();
var actual = SyntaxTree.Parse(input).Format();
Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
}

[Fact]
public void SimpleExpressionShouldBeFormattedCorrectly()
{
var input = """
func aLongMethodName() = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
""";
var expected = """
func aLongMethodName() = 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10;

""";
var actual = SyntaxTree.Parse(input).Format(new Internal.Syntax.Formatting.FormatterSettings()
{
LineWidth = 60
});
Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
}

[Fact]
public void ExpressionInMultiLineStringDoesNotChange()
{
var input = """"
func main() {
val someMultiLineString = """
the result:\{1 + 2 + 3 + 4 + 5
+ 6 + 7 + 8 + 9 + 10}
""";
}

"""";
var actual = SyntaxTree.Parse(input).Format(new Internal.Syntax.Formatting.FormatterSettings()
{
LineWidth = 50
});
Assert.Equal(input, actual, ignoreLineEndingDifferences: true);
}

[Fact]
public void MultiReturnInMultiLineStringArePreserved()
{
var input = """"
func main() {
val someMultiLineString = """
bla bla


bla bla

""";
}

"""";
var actual = SyntaxTree.Parse(input).Format();
Assert.Equal(input, actual, ignoreLineEndingDifferences: true);
}

[Fact]
public void MultiReturnInMultiLineStringArePreserved2()
{
var input = """"
func main() {
val someMultiLineString = """
bla bla


bla bla


""";
}

"""";
var actual = SyntaxTree.Parse(input).Format();
Assert.Equal(input, actual, ignoreLineEndingDifferences: true);
}

[Fact]
public void IfElseChainFormatsCorrectly()
{
var input = """"
func main() {
if (false)
expr1
else if (false)
expr2
else if (false) expr3
else expr4
}
"""";
var expected = """"
func main() {
if (false) expr1
else if (false) expr2
else if (false) expr3
else expr4
}

"""";
var actual = SyntaxTree.Parse(input).Format();
Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
}

[Fact]
public void TooLongArgsFoldsInsteadOfExpr()
{
var input = """
func main(lots: Of, arguments: That, will: Be, fold: But) = nnot + this;
""";
var expected = """
func main(
lots: Of,
arguments: That,
will: Be,
fold: But) = nnot + this;

""";
var actual = SyntaxTree.Parse(input).Format(new Internal.Syntax.Formatting.FormatterSettings()
{
LineWidth = 60
});
Assert.Equal(expected, actual, ignoreLineEndingDifferences: true);
}

[Fact]
public void NoLineReturnInSingleLineString()
{
var input = """"
func main() {
val value = "Value: \{if (input < value) "low" else "high"}";
}

"""";
var actual = SyntaxTree.Parse(input).Format(new Internal.Syntax.Formatting.FormatterSettings()
{
LineWidth = 10
});
Assert.Equal(input, actual, ignoreLineEndingDifferences: true);
}

[Fact]
public void Sample1()
{
var input = """"
import System;
import System.Console;

func main() {
val value = Random.Shared.Next(1, 101);
while (true) {
Write("Guess a number (1-100): ");
val input = Convert.ToInt32(ReadLine());
if (input == value) goto break;
WriteLine("Incorrect. Too \{if (input < value) "low" else "high"}");
}
WriteLine("You guessed it!");
}

"""";
var actual = SyntaxTree.Parse(input).Format(new Internal.Syntax.Formatting.FormatterSettings()
{
LineWidth = 50
});
Assert.Equal(input, actual, ignoreLineEndingDifferences: true);
}

[Fact]
public void CursedSample()
{
var input = """"
//test
func //test
main
// another
// foobar
() {
var
// test
opponent = "R";
var me = "P";
if // heh
(me == opponent) return println("draw");
if (
// heh
me == "R") {
println(if (opponent == "P") "lose" else "win");
}
else if ( // heh
me == "P") {
println(if (opponent == "R") "win" else "lose");
}
else if (me == "S") {
println(if (opponent == "P") "win" else "lose");
}
} // oh hello
// oops.

"""";
var actual = SyntaxTree.Parse(input).Format();
logger.WriteLine(actual);
Assert.Equal(input, actual, ignoreLineEndingDifferences: true);
}

[Fact]
public void CursedSample2()
{
var input = """"
func foo(a: int32) {
if ({
var x = a * 2;
x > 50
}) {
WriteLine("ohno");
}
}

"""";
var actual = SyntaxTree.Parse(input).Format();
logger.WriteLine(actual);
Assert.Equal(input, actual, ignoreLineEndingDifferences: true);
}
}
11 changes: 11 additions & 0 deletions src/Draco.Compiler/Api/Syntax/ElseClauseSyntax.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Draco.Compiler.Api.Syntax;

public partial class ElseClauseSyntax
{
/// <summary>
/// Returns <see langword="true"/> when the else clause is followed by an if expression.
/// </summary>
public bool IsElseIf => this.Expression is StatementExpressionSyntax statementExpression
Kuinox marked this conversation as resolved.
Show resolved Hide resolved
Kuinox marked this conversation as resolved.
Show resolved Hide resolved
&& statementExpression.Statement is ExpressionStatementSyntax expressionStatement
&& expressionStatement.Expression is IfExpressionSyntax;
}
1 change: 0 additions & 1 deletion src/Draco.Compiler/Api/Syntax/SeparatedSyntaxList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Linq;
using System.Reflection;
using System.Threading;
using Draco.Compiler.Internal;

namespace Draco.Compiler.Api.Syntax;

Expand Down
11 changes: 11 additions & 0 deletions src/Draco.Compiler/Api/Syntax/StringPartSyntax.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Linq;

namespace Draco.Compiler.Api.Syntax;
public partial class StringPartSyntax
{
/// <summary>
/// <see langword="true"/> when this <see cref="StringPartSyntax"/> is a <see cref="SyntaxToken"/> with <see cref="TokenKind.StringNewline"/>.
/// </summary>
public bool IsNewLine => this.Children.Count() == 1 && this.Children.SingleOrDefault() is SyntaxToken and { Kind: TokenKind.StringNewline };
Kuinox marked this conversation as resolved.
Show resolved Hide resolved
}
1 change: 0 additions & 1 deletion src/Draco.Compiler/Api/Syntax/SyntaxList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Linq;
using System.Reflection;
using System.Threading;
using Draco.Compiler.Internal;

namespace Draco.Compiler.Api.Syntax;

Expand Down
3 changes: 1 addition & 2 deletions src/Draco.Compiler/Api/Syntax/SyntaxTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Linq;
using System.Threading;
using Draco.Compiler.Api.Diagnostics;
using Draco.Compiler.Internal;
using Draco.Compiler.Internal.Syntax;
using Draco.Compiler.Internal.Syntax.Formatting;
using Draco.Compiler.Internal.Syntax.Rewriting;
Expand Down Expand Up @@ -157,7 +156,7 @@ public ImmutableArray<TextEdit> SyntaxTreeDiff(SyntaxTree other) =>
/// Syntactically formats this <see cref="SyntaxTree"/>.
/// </summary>
/// <returns>The formatted tree.</returns>
public SyntaxTree Format() => Formatter.Format(this);
public string Format(FormatterSettings? settings = null) => DracoFormatter.Format(this, settings);

/// <summary>
/// The internal root of the tree.
Expand Down
1 change: 1 addition & 0 deletions src/Draco.Compiler/Draco.Compiler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Draco.FormatterEngine\Draco.FormatterEngine.csproj" />
<ProjectReference Include="..\Draco.SourceGeneration\Draco.SourceGeneration.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="False" />
</ItemGroup>

Expand Down
1 change: 0 additions & 1 deletion src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Collections.Immutable;
using System.Linq;
using Draco.Compiler.Api.Syntax;
using Draco.Compiler.Internal.BoundTree;
using Draco.Compiler.Internal.Diagnostics;
using Draco.Compiler.Internal.Solver;
using Draco.Compiler.Internal.Solver.Tasks;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Draco.Compiler.Api.Diagnostics;

namespace Draco.Compiler.Internal.Diagnostics;
Expand Down
Loading
Loading