Skip to content

Commit

Permalink
Merge pull request #1124 from TymurGubayev/fix/StaticsWithSameNameInG…
Browse files Browse the repository at this point in the history
…etAndSet/1

Differentiate between statics in setters and getters
  • Loading branch information
GrahamTheCoder authored Jul 27, 2024
2 parents eb5d1c7 + 430d49b commit c3a91c8
Show file tree
Hide file tree
Showing 7 changed files with 82 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);
}

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 MethodKind 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, MethodKind 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 == MethodKind.Ordinary ? "" : OriginalParentAccessorKind.ToString(), 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;

MethodKind parentAccessorKind = MethodKind.Ordinary;
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) ? MethodKind.PropertyGet : MethodKind.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 (field.OriginalParentAccessorKind != MethodKind.Ordinary) {
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, MethodKind accessorKind) where T : SyntaxNode
{
return node.WithAdditionalAnnotations(AnnotationConstants.ParentPropertyAccessorKind(accessorKind.ToString()));
}

private static bool IsBlockParent(SyntaxNode converted, SyntaxToken lastCsConvertedToken)
{
return lastCsConvertedToken.Parent == converted || lastCsConvertedToken.Parent is BlockSyntax b && b.Parent == converted;
Expand Down
39 changes: 39 additions & 0 deletions Tests/CSharp/MemberTests/MemberTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,45 @@ public void set_Prop(int i, string value)
_Prop_bSet = false;
}
}");
}

[Fact]
public async Task StaticLocalsInPropertyGetterAndSetterAsync()
{
await TestConversionVisualBasicToCSharpAsync(
@"
Public Property Prop As String
Get
Static b As Boolean
b = True
End Get
Set(ByVal s As String)
Static b As Boolean
b = False
End Set
End Property
", @"
internal partial class SurroundingClass
{
private bool _Prop_b;
private bool _Prop_b1;
public string Prop
{
get
{
_Prop_b = true;
return default;
}
set
{
_Prop_b1 = false;
}
}
}");
}

Expand Down

0 comments on commit c3a91c8

Please sign in to comment.