Skip to content

Commit

Permalink
differentiate between statics in setters and getters
Browse files Browse the repository at this point in the history
  • Loading branch information
Timur Kelman authored and Timur Kelman committed Jul 23, 2024
1 parent 236f724 commit 2208e30
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CodeConverter/CSharp/ExpressionNodeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1544,6 +1544,10 @@ public override async Task<CSharpSyntaxNode> VisitIdentifierName(VBasic.Syntax.I

var sym = GetSymbolInfoInDocument<ISymbol>(node);
if (sym is ILocalSymbol) {
if (sym.IsStatic && sym.ContainingSymbol is IMethodSymbol m && m.AssociatedSymbol is IPropertySymbol) {
qualifiedIdentifier = qualifiedIdentifier.WithParentPropertyAccessorKind(m.MethodKind.ToString());
}

var vbMethodBlock = node.Ancestors().OfType<VBasic.Syntax.MethodBlockBaseSyntax>().FirstOrDefault();
if (vbMethodBlock != null &&
vbMethodBlock.MustReturn() &&
Expand Down
5 changes: 4 additions & 1 deletion CodeConverter/CSharp/HoistedFieldFromVbStaticVariable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,21 @@ internal class HoistedFieldFromVbStaticVariable : IHoistedNode
{
public string OriginalMethodName { get; }
public string OriginalVariableName { get; }
public string OriginalParentAccessorKind { get; }
public ExpressionSyntax Initializer { get; }
public TypeSyntax Type { get; }
public bool IsStatic { get; }

public HoistedFieldFromVbStaticVariable(string originalMethodName, string originalVariableName, ExpressionSyntax initializer, TypeSyntax type, bool isStatic)
public HoistedFieldFromVbStaticVariable(string originalMethodName, string originalVariableName, string originalParentAccessorKind, ExpressionSyntax initializer, TypeSyntax type, bool isStatic)
{
OriginalMethodName = originalMethodName;
OriginalVariableName = originalVariableName;
OriginalParentAccessorKind = originalParentAccessorKind;
Initializer = initializer;
Type = type;
IsStatic = isStatic;
}

public string FieldName => OriginalMethodName != null ? $"_{OriginalMethodName}_{OriginalVariableName}" : $"_{OriginalVariableName}";
public string PrefixedOriginalVariableName => PerScopeState.GetPrefixedName(OriginalParentAccessorKind, OriginalVariableName);
}
4 changes: 3 additions & 1 deletion CodeConverter/CSharp/MethodBodyExecutableStatementVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ public override async Task<SyntaxList<StatementSyntax>> VisitLocalDeclarationSta
string methodName;
SyntaxTokenList methodModifiers;

string parentAccessorKind = null;
if (_methodNode is VBSyntax.MethodBlockSyntax methodBlock) {
var methodStatement = methodBlock.BlockStatement as VBSyntax.MethodStatementSyntax;
methodModifiers = methodStatement.Modifiers;
Expand All @@ -120,13 +121,14 @@ public override async Task<SyntaxList<StatementSyntax>> VisitLocalDeclarationSta
} else if (_methodNode is VBSyntax.AccessorBlockSyntax accessorBlock) {
var propertyBlock = accessorBlock.Parent as VBSyntax.PropertyBlockSyntax;
methodName = propertyBlock.PropertyStatement.Identifier.Text;
parentAccessorKind = accessorBlock.IsKind(VBasic.SyntaxKind.GetAccessorBlock) ? "PropertyGet" : "PropertySet";
methodModifiers = propertyBlock.PropertyStatement.Modifiers;
} else {
throw new NotImplementedException(_methodNode.GetType() + " not implemented!");
}

var isVbShared = methodModifiers.Any(a => a.IsKind(VBasic.SyntaxKind.SharedKeyword));
_perScopeState.HoistToTopLevel(new HoistedFieldFromVbStaticVariable(methodName, variable.Identifier.Text, initializeValue, decl.Declaration.Type, isVbShared));
_perScopeState.HoistToTopLevel(new HoistedFieldFromVbStaticVariable(methodName, variable.Identifier.Text, parentAccessorKind, initializeValue, decl.Declaration.Type, isVbShared));
}
} else {
var shouldPullVariablesBeforeLoop = _perScopeState.IsInsideLoop() && declarator.Initializer is null && declarator.AsClause is not VBSyntax.AsNewClauseSyntax;
Expand Down
26 changes: 21 additions & 5 deletions CodeConverter/CSharp/PerScopeState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,18 +157,22 @@ public async Task<SyntaxList<MemberDeclarationSyntax>> CreateVbStaticFieldsAsync
var declarations = new List<FieldDeclarationSyntax>();

var fieldInfo = GetFields();
var newNames = fieldInfo.ToDictionary(f => f.OriginalVariableName, f =>
var newNames = fieldInfo.ToDictionary(f => f.PrefixedOriginalVariableName, f =>
NameGenerator.CS.GetUniqueVariableNameInScope(semanticModel, generatedNames, typeNode, f.FieldName)
);
foreach (var field in fieldInfo) {
var decl = (field.Initializer != null)
? CommonConversions.CreateVariableDeclarationAndAssignment(newNames[field.OriginalVariableName], field.Initializer, field.Type)
: SyntaxFactory.VariableDeclaration(field.Type, SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(newNames[field.OriginalVariableName])));
? CommonConversions.CreateVariableDeclarationAndAssignment(newNames[field.PrefixedOriginalVariableName], field.Initializer, field.Type)
: SyntaxFactory.VariableDeclaration(field.Type, SyntaxFactory.SingletonSeparatedList(SyntaxFactory.VariableDeclarator(newNames[field.PrefixedOriginalVariableName])));
var modifiers = new List<SyntaxToken> { CS.SyntaxFactory.Token(SyntaxKind.PrivateKeyword) };
if (field.IsStatic || namedTypeSymbol.IsModuleType()) {
modifiers.Add(CS.SyntaxFactory.Token(SyntaxKind.StaticKeyword));
}
declarations.Add(CS.SyntaxFactory.FieldDeclaration(CS.SyntaxFactory.List<AttributeListSyntax>(), CS.SyntaxFactory.TokenList(modifiers), decl));
var fieldDecl = CS.SyntaxFactory.FieldDeclaration(CS.SyntaxFactory.List<AttributeListSyntax>(), CS.SyntaxFactory.TokenList(modifiers), decl);
if (!string.IsNullOrEmpty(field.OriginalParentAccessorKind)) {
fieldDecl = fieldDecl.WithParentPropertyAccessorKind(field.OriginalParentAccessorKind);
}
declarations.Add(fieldDecl);
}

var statementsWithUpdatedIds = ReplaceNames(declarations.Concat(csNodes), newNames);
Expand All @@ -185,11 +189,23 @@ public static IEnumerable<T> ReplaceNames<T>(IEnumerable<T> csNodes, Dictionary<
public static T ReplaceNames<T>(T csNode, Dictionary<string, string> newNames) where T : SyntaxNode
{
return csNode.ReplaceNodes(csNode.DescendantNodesAndSelf().OfType<IdentifierNameSyntax>(), (_, idns) => {
if (newNames.TryGetValue(idns.Identifier.ValueText, out var newName)) {
if (TryGetValue(newNames, idns, out var newName)) {
return idns.WithoutAnnotations(AdditionalLocalAnnotation).WithIdentifier(CS.SyntaxFactory.Identifier(newName));
}
return idns;
});

static bool TryGetValue(Dictionary<string, string> newNames, IdentifierNameSyntax idns, out string newName)
{
var ann = idns.GetAnnotations(AnnotationConstants.ParentPropertyAccessorKindAnnotation).FirstOrDefault();
var key = GetPrefixedName(ann?.Data, idns.Identifier.ValueText);
return newNames.TryGetValue(key, out newName);
}
}

internal static string GetPrefixedName(string prefix, string name)
{
return string.IsNullOrEmpty(prefix) ? name : $"<{prefix}>.{name}";
}

public IEnumerable<StatementSyntax> ConvertExit(VBasic.SyntaxKind vbBlockKeywordKind)
Expand Down
6 changes: 6 additions & 0 deletions CodeConverter/Common/AnnotationConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ internal static class AnnotationConstants
public const string SourceEndLineAnnotationKind = "CodeConverter.SourceEndLine";
public const string LeadingTriviaAlreadyMappedAnnotation = nameof(CodeConverter) + "." + nameof(LeadingTriviaAlreadyMappedAnnotation);
public const string TrailingTriviaAlreadyMappedAnnotation = nameof(CodeConverter) + "." + nameof(TrailingTriviaAlreadyMappedAnnotation);
public const string ParentPropertyAccessorKindAnnotation = nameof(CodeConverter) + "." + nameof(ParentPropertyAccessorKindAnnotation);

private static string AsString(LinePosition position)
{
Expand Down Expand Up @@ -40,4 +41,9 @@ public static SyntaxAnnotation SourceEndLine(FileLinePositionSpan origLinespan)
{
return new SyntaxAnnotation(SourceEndLineAnnotationKind, origLinespan.EndLinePosition.Line.ToString(CultureInfo.InvariantCulture));
}

public static SyntaxAnnotation ParentPropertyAccessorKind(string accessorKind)
{
return new SyntaxAnnotation(ParentPropertyAccessorKindAnnotation, accessorKind);
}
}
5 changes: 5 additions & 0 deletions CodeConverter/Util/SyntaxNodeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ private static T WithoutSourceMappingNonRecursive<T>(this T node) where T : Synt
return node.WithoutAnnotations(AnnotationConstants.SourceStartLineAnnotationKind).WithoutAnnotations(AnnotationConstants.SourceEndLineAnnotationKind);
}

public static T WithParentPropertyAccessorKind<T>(this T node, string accessorKind) where T : SyntaxNode
{
return node.WithAdditionalAnnotations(AnnotationConstants.ParentPropertyAccessorKind(accessorKind));
}

private static bool IsBlockParent(SyntaxNode converted, SyntaxToken lastCsConvertedToken)
{
return lastCsConvertedToken.Parent == converted || lastCsConvertedToken.Parent is BlockSyntax b && b.Parent == converted;
Expand Down

0 comments on commit 2208e30

Please sign in to comment.