Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions src/SharpIDE.Godot/SharpIDE.Godot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,17 @@
<DoNotPublicize Include="Microsoft.CodeAnalysis.Workspaces:System.Linq.RoslynEnumerableExtensions" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\SharpIDE.SourceGenerators\SharpIDE.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>

<ItemGroup>
<None Include="version.txt" />
</ItemGroup>

<ItemGroup>
<None Remove="project.godot"/>
<AdditionalFiles Include="project.godot"/>
</ItemGroup>

</Project>
8 changes: 8 additions & 0 deletions src/SharpIDE.Godot/SharpIDE.Godot.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
..\..\.globalconfig = ..\..\.globalconfig
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpIDE.SourceGenerators", "..\SharpIDE.SourceGenerators\SharpIDE.SourceGenerators.csproj", "{3EE9E01D-5C04-4C6D-89DD-D85F1F527976}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -44,5 +46,11 @@ Global
{DFF170D9-D92E-4DB7-83B5-19640EAF79D2}.ExportDebug|Any CPU.Build.0 = Debug|Any CPU
{DFF170D9-D92E-4DB7-83B5-19640EAF79D2}.ExportRelease|Any CPU.ActiveCfg = Debug|Any CPU
{DFF170D9-D92E-4DB7-83B5-19640EAF79D2}.ExportRelease|Any CPU.Build.0 = Debug|Any CPU
{3EE9E01D-5C04-4C6D-89DD-D85F1F527976}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3EE9E01D-5C04-4C6D-89DD-D85F1F527976}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3EE9E01D-5C04-4C6D-89DD-D85F1F527976}.ExportDebug|Any CPU.ActiveCfg = Debug|Any CPU
{3EE9E01D-5C04-4C6D-89DD-D85F1F527976}.ExportDebug|Any CPU.Build.0 = Debug|Any CPU
{3EE9E01D-5C04-4C6D-89DD-D85F1F527976}.ExportRelease|Any CPU.ActiveCfg = Debug|Any CPU
{3EE9E01D-5C04-4C6D-89DD-D85F1F527976}.ExportRelease|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,6 @@

namespace SharpIDE.Godot;

public static class InputStringNames
{
public static readonly StringName RenameSymbol = nameof(RenameSymbol);
public static readonly StringName CodeFixes = nameof(CodeFixes);
public static readonly StringName StepOver = nameof(StepOver);
public static readonly StringName FindInFiles = nameof(FindInFiles);
public static readonly StringName FindFiles = nameof(FindFiles);
public static readonly StringName SaveFile = nameof(SaveFile);
public static readonly StringName SaveAllFiles = nameof(SaveAllFiles);
}

public static class ThemeStringNames
{
public static readonly StringName Font = "font";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace SharpIDE.SourceGenerators.InputMapName;

public class InputMapNameConstants
{
public const string PropertiesPlaceholder = "{Properties}";
public const string Code = $$"""
// <auto-generated/>
using Godot;
namespace SharpIDE.Godot;

public static partial class InputStringNames
{
{{PropertiesPlaceholder}}
}
""";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.CodeAnalysis;

namespace SharpIDE.SourceGenerators.InputMapName;

[Generator]
public class InputMapNameGenerator : IIncrementalGenerator
{
private static readonly Regex _inputNameRegex = new(@"\b(\w+)\s*=\s*\{", RegexOptions.Compiled);

public void Initialize(IncrementalGeneratorInitializationContext context)
{
var inputMapNamesProvider = context.AdditionalTextsProvider
.Where(at => Path.GetFileName(at.Path).Equals("project.godot", StringComparison.OrdinalIgnoreCase));
context.RegisterSourceOutput(inputMapNamesProvider, GenerateInputMapNames);
}

private static void GenerateInputMapNames(SourceProductionContext context, AdditionalText additionalText)
{
var text = additionalText.GetText(context.CancellationToken);
if (text is null)
return;

// Parse the input map names from the project.godot file
var matchCollection = _inputNameRegex.Matches(text.ToString());
var inputMapNames = matchCollection.Cast<Match>().Select(match => match.Groups[1].Value).ToList();

// Generate the source code
var sourceText = InputMapNameConstants.Code.Replace(InputMapNameConstants.PropertiesPlaceholder, GenerateProperties(inputMapNames));

// Add the source code to the compilation
context.AddSource("InputMapNames.g.cs", sourceText);
}

private static string GenerateProperties(IEnumerable<string> inputMapNames)
{
var propertiesBuilder = new System.Text.StringBuilder();
foreach (var name in inputMapNames)
{
var safeName = SanitizeIdentifier(name);
propertiesBuilder.AppendLine($"\tpublic const string {safeName} = \"{name}\";");
}
return propertiesBuilder.ToString();
}
/// <summary>
/// Sanitizes a string to be a valid C# identifier.
/// Replaces invalid characters with underscores and ensures the identifier does not start with a digit.
/// </summary>
private static string SanitizeIdentifier(string name)
{
if (string.IsNullOrEmpty(name))
return "_";

// Remove invalid characters
var sanitized = Regex.Replace(name, "[^a-zA-Z0-9_]", "");

// If the first character is not a letter or underscore, prefix with underscore
if (!char.IsLetter(sanitized, 0) && sanitized[0] != '_')
sanitized = "_" + sanitized;

return sanitized;
}
}
9 changes: 9 additions & 0 deletions src/SharpIDE.SourceGenerators/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"SharpIDE.SourceGenerators": {
"commandName": "DebugRoslynComponent",
"targetProject": "../SharpIDE.Godot/SharpIDE.Godot.csproj"
}
}
}
26 changes: 26 additions & 0 deletions src/SharpIDE.SourceGenerators/SharpIDE.SourceGenerators.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<EnableCentralPackageVersions>false</EnableCentralPackageVersions>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
<TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>

<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>

<RootNamespace>SharpIDE.SourceGenerators</RootNamespace>
<PackageId>SharpIDE.SourceGenerators</PackageId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
</ItemGroup>

</Project>