C#: Preserve order of exported fields/categories

This commit is contained in:
Paul Joannon 2022-08-15 10:53:08 +02:00
parent f03ac21ea8
commit cf99d92a39
No known key found for this signature in database
GPG Key ID: C12F69B0AD0390DD
3 changed files with 41 additions and 18 deletions

View File

@ -275,5 +275,13 @@ namespace Godot.SourceGenerators
yield return new GodotFieldData(field, marshalType.Value);
}
}
public static string Path(this Location location)
=> location.SourceTree?.GetLineSpan(location.SourceSpan).Path
?? location.GetLineSpan().Path;
public static int StartLine(this Location location)
=> location.SourceTree?.GetLineSpan(location.SourceSpan).StartLinePosition.Line
?? location.GetLineSpan().StartLinePosition.Line;
}
}

View File

@ -59,4 +59,26 @@ namespace Godot.SourceGenerators
public IFieldSymbol FieldSymbol { get; }
public MarshalType Type { get; }
}
public struct GodotPropertyOrFieldData
{
public GodotPropertyOrFieldData(ISymbol symbol, MarshalType type)
{
Symbol = symbol;
Type = type;
}
public GodotPropertyOrFieldData(GodotPropertyData propertyData)
: this(propertyData.PropertySymbol, propertyData.Type)
{
}
public GodotPropertyOrFieldData(GodotFieldData fieldData)
: this(fieldData.FieldSymbol, fieldData.Type)
{
}
public ISymbol Symbol { get; }
public MarshalType Type { get; }
}
}

View File

@ -225,28 +225,21 @@ namespace Godot.SourceGenerators
.Append(dictionaryType)
.Append("();\n");
foreach (var property in godotClassProperties)
// To retain the definition order (and display categories correctly), we want to
// iterate over fields and properties at the same time, sorted by line number.
var godotClassPropertiesAndFields = Enumerable.Empty<GodotPropertyOrFieldData>()
.Concat(godotClassProperties.Select(propertyData => new GodotPropertyOrFieldData(propertyData)))
.Concat(godotClassFields.Select(fieldData => new GodotPropertyOrFieldData(fieldData)))
.OrderBy(data => data.Symbol.Locations[0].Path())
.ThenBy(data => data.Symbol.Locations[0].StartLine());
foreach (var member in godotClassPropertiesAndFields)
{
foreach (var groupingInfo in DetermineGroupingPropertyInfo(property.PropertySymbol))
foreach (var groupingInfo in DetermineGroupingPropertyInfo(member.Symbol))
AppendGroupingPropertyInfo(source, groupingInfo);
var propertyInfo = DeterminePropertyInfo(context, typeCache,
property.PropertySymbol, property.Type);
if (propertyInfo == null)
continue;
AppendPropertyInfo(source, propertyInfo.Value);
}
foreach (var field in godotClassFields)
{
foreach (var groupingInfo in DetermineGroupingPropertyInfo(field.FieldSymbol))
AppendGroupingPropertyInfo(source, groupingInfo);
var propertyInfo = DeterminePropertyInfo(context, typeCache,
field.FieldSymbol, field.Type);
member.Symbol, member.Type);
if (propertyInfo == null)
continue;