Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
1 change: 1 addition & 0 deletions cspell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ words:
- debugpy
- Declipse
- dedented
- Dedup
Comment thread
jorgerangel-msft marked this conversation as resolved.
Outdated
- Dedupes
- deps
- destructures
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Microsoft.TypeSpec.Generator.Primitives;
using Microsoft.TypeSpec.Generator.Providers;
using Microsoft.TypeSpec.Generator.Statements;

Expand All @@ -10,16 +11,25 @@ public sealed record MemberExpression(ValueExpression? Inner, string MemberName)
{
public ValueExpression? Inner { get; internal set; } = Inner;
public string MemberName { get; private set; } = MemberName;
internal CodeWriterDeclaration? Declaration { get; set; }
internal override void Write(CodeWriter writer)
{
if (Inner is not null)
{
Inner.Write(writer);
writer.AppendRaw(".");
}
// workaround to avoid Roslyn reducing properties named Object to object
// Should come up with a better approach - https://github.com/microsoft/typespec/issues/4724
writer.AppendRaw(MemberName == "Object" && Inner == null ? $"this.{MemberName}" : MemberName);

if (Declaration is not null)
{
writer.Append(Declaration, referenceOnly: true);
}
else
{
// workaround to avoid Roslyn reducing properties named Object to object
// Should come up with a better approach - https://github.com/microsoft/typespec/issues/4724
writer.AppendRaw(MemberName == "Object" && Inner == null ? $"this.{MemberName}" : MemberName);
}
}

internal override ValueExpression? Accept(LibraryVisitor visitor, MethodProvider method)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ public void Update(
_variable?.Update(name: name);
_asMember?.Update(memberName: name);
_declaration = null;
if (_asMember != null)
{
_asMember.Declaration = Declaration;
Comment thread
jorgerangel-msft marked this conversation as resolved.
}
InitializeParameter();
}

Expand Down Expand Up @@ -148,6 +152,6 @@ private void InitializeParameter()
}

private MemberExpression? _asMember;
public static implicit operator MemberExpression(FieldProvider field) => field._asMember ??= new MemberExpression(null, field.Name);
public static implicit operator MemberExpression(FieldProvider field) => field._asMember ??= new MemberExpression(null, field.Name) { Declaration = field.Declaration };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1004,12 +1004,16 @@ public CodeScope AmbientScope()
return codeWriterScope;
}

internal void Append(CodeWriterDeclaration declaration)
internal void Append(CodeWriterDeclaration declaration, bool referenceOnly = false)
{
if (declaration.HasBeenDeclared(_scopes))
{
WriteIdentifier(declaration.GetActualName(_scopes.Peek()));
}
else if (referenceOnly)
{
WriteIdentifier(declaration.RequestedName);
}
else
{
WriteDeclaration(declaration);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,35 @@ public void ScopeDeclaredTwiceForMethodSignatureParam()
Assert.AreEqual(Helpers.GetExpectedFromFile(), codeWriter.ToString(false));
}

[Test]
public void FieldDedupUpdatesReferencesViaMemberExpression()
{
var type = new TestTypeProvider();
var field1 = new FieldProvider(FieldModifiers.Private | FieldModifiers.ReadOnly, typeof(string), "_scope", type);
var field2 = new FieldProvider(FieldModifiers.Private | FieldModifiers.ReadOnly, typeof(string), "_scope", type);

using var codeWriter = new CodeWriter();
// Write both field declarations - the second should be deduped to _scope0
codeWriter.WriteField(field1);
codeWriter.WriteField(field2);
// Write a reference to the second field via AsValueExpression (implicit MemberExpression)
field2.AsValueExpression.Write(codeWriter);
Assert.AreEqual(Helpers.GetExpectedFromFile(), codeWriter.ToString(false));
}

[Test]
public void FieldReferenceBeforeDeclarationUsesRequestedName()
{
var type = new TestTypeProvider();
var field = new FieldProvider(FieldModifiers.Private | FieldModifiers.ReadOnly, typeof(string), "_token", type);

using var codeWriter = new CodeWriter();
// Write a reference BEFORE the field declaration — should use the original name, not create a declaration
field.AsValueExpression.Write(codeWriter);
codeWriter.WriteField(field);
Assert.AreEqual(Helpers.GetExpectedFromFile(), codeWriter.ToString(false));
}

private Dictionary<CodeWriter.CodeScope, string> GetDeclarationScopes(CodeWriterDeclaration declaration)
{
var namesDictionaryField = typeof(CodeWriterDeclaration).GetField("_actualNames", BindingFlags.NonPublic | BindingFlags.Instance);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
private readonly string _scope;
private readonly string _scope0;
_scope0
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_tokenprivate readonly string _token;