Skip to content

Commit

Permalink
Better Identifier Emission & State Handling (#891)
Browse files Browse the repository at this point in the history
  • Loading branch information
HurricanKai committed Apr 19, 2022
1 parent d40fdf3 commit 75c3600
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 3 deletions.
49 changes: 46 additions & 3 deletions src/generators/Silk.NET.SilkTouch.Emitter/CSharpEmitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
Expand Down Expand Up @@ -50,14 +51,22 @@ private class Visitor : Silk.NET.SilkTouch.Symbols.SymbolVisitor
{
public CSharpSyntaxNode? Syntax => _syntax;
private CSharpSyntaxNode? _syntax = null;
private SyntaxToken? _syntaxToken = null;

protected override StructSymbol VisitStruct(StructSymbol structSymbol)
{
AssertClearState();

VisitIdentifier(structSymbol.Identifier);
if (_syntaxToken is not { } identifierToken)
throw new InvalidOperationException("Field Identifier was not visited correctly");
ClearState();

var members = List<MemberDeclarationSyntax>();
var modifiers = TokenList(Token(SyntaxTriviaList.Empty, SyntaxKind.PublicKeyword, TriviaList(Space)));
_syntax = StructDeclaration
(
List<AttributeListSyntax>(), modifiers, Identifier(structSymbol.Identifier.Value), null, null,
List<AttributeListSyntax>(), modifiers, identifierToken, null, null,
List<TypeParameterConstraintClauseSyntax>(), members
)
.WithKeyword(Token(SyntaxTriviaList.Empty, SyntaxKind.StructKeyword, TriviaList(Space)));
Expand All @@ -66,21 +75,55 @@ protected override StructSymbol VisitStruct(StructSymbol structSymbol)

protected override FieldSymbol VisitField(FieldSymbol fieldSymbol)
{
AssertClearState();

VisitIdentifier(fieldSymbol.Type.Identifier);
if (_syntax is not IdentifierNameSyntax typeIdentifierSyntax)
throw new InvalidOperationException("Field type Identifier was not visited correctly");
ClearState();

VisitIdentifier(fieldSymbol.Identifier);
if (_syntaxToken is not { } identifierToken)
throw new InvalidOperationException("Field Identifier was not visited correctly");
ClearState();

_syntax = FieldDeclaration
(
List<AttributeListSyntax>(),
TokenList(Token(SyntaxTriviaList.Empty, SyntaxKind.PublicKeyword, TriviaList(Space))),
VariableDeclaration
(
IdentifierName(fieldSymbol.Type.Identifier.Value),
typeIdentifierSyntax,
SingletonSeparatedList
(
VariableDeclarator
(Identifier(TriviaList(Space), fieldSymbol.Identifier.Value, SyntaxTriviaList.Empty))
(identifierToken.WithLeadingTrivia(TriviaList(Space)))
)
)
);
return fieldSymbol;
}

protected override IdentifierSymbol VisitIdentifier(IdentifierSymbol identifierSymbol)
{
AssertClearState();

_syntaxToken = Identifier(SyntaxTriviaList.Empty, identifierSymbol.Value, SyntaxTriviaList.Empty);
_syntax = IdentifierName(_syntaxToken.Value);
return identifierSymbol;
}

[Conditional("DEBUG")]
private void AssertClearState()
{
Debug.Assert(_syntax is null);
Debug.Assert(!_syntaxToken.HasValue);
}

private void ClearState()
{
_syntax = null;
_syntaxToken = null;
}
}
}
36 changes: 36 additions & 0 deletions tests/Silk.NET.SilkTouch.Emitter.Tests/IdentifierTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Silk.NET.SilkTouch.Symbols;
using Xunit;

namespace Silk.NET.SilkTouch.Emitter.Tests;

public sealed class IdentifierTests : EmitterTest
{
[Fact]
public void IdentifierHasNoLeadingTrivia()
{
var node = Transform(new IdentifierSymbol("Test"));

Assert.Empty(node.GetLeadingTrivia());
Assert.False(node.HasLeadingTrivia);
}

[Fact]
public void IdentifierHasNoTrailingTrivia()
{
var node = Transform(new IdentifierSymbol("Test"));

Assert.Empty(node.GetTrailingTrivia());
Assert.False(node.HasTrailingTrivia);
}

[Fact]
public void IdentifierIntegration()
{
var node = Transform(new IdentifierSymbol("Test"));

Assert.Equal("Test", node.ToFullString());
}
}

0 comments on commit 75c3600

Please sign in to comment.