提交 9e67e472 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #20958 from CyrusNajmabadi/genConstructorWithoutFields

Offer to not generate fields when generating a new constructor.
......@@ -46,6 +46,30 @@ void M()
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestWithSimpleArgument_NoFields()
{
await TestInRegularAndScriptAsync(
@"class C
{
void M()
{
new [|C|](1);
}
}",
@"class C
{
public C(int v)
{
}
void M()
{
new C(1);
}
}", index: 1);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestWithSimpleArgument_UseExpressionBody1()
{
......@@ -72,7 +96,7 @@ public C(int v) => this.v = v; void M()
[Fact, WorkItem(910589, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/910589"), Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestWithNoArgs()
{
await TestInRegularAndScriptAsync(
var input =
@"class C
{
public C(int v)
......@@ -83,7 +107,11 @@ void M()
{
new [|C|]();
}
}",
}";
await TestActionCountAsync(input, 1);
await TestInRegularAndScriptAsync(
input,
@"class C
{
public C()
......@@ -131,7 +159,7 @@ void M()
[Fact, WorkItem(910589, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/910589"), Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestWithExistingField1()
{
await TestInRegularAndScriptAsync(
const string input =
@"class C
{
void M()
......@@ -143,7 +171,10 @@ void M()
class D
{
private int foo;
}",
}";
await TestActionCountAsync(input, 1);
await TestInRegularAndScriptAsync(
input,
@"class C
{
void M()
......@@ -199,6 +230,40 @@ public D(int v1)
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestWithExistingField2_NoFields()
{
await TestInRegularAndScriptAsync(
@"class C
{
void M()
{
new [|D|](1);
}
}
class D
{
private string v;
}",
@"class C
{
void M()
{
new D(1);
}
}
class D
{
private string v;
public D(int v1)
{
}
}", index: 1);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestWithExistingField3()
{
......@@ -953,7 +1018,7 @@ public D(out int i)
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestWithBaseDelegatingConstructor1()
{
await TestInRegularAndScriptAsync(
const string input =
@"class C
{
void M()
......@@ -971,7 +1036,11 @@ protected B(int x)
class D : B
{
}",
}";
await TestActionCountAsync(input, 1);
await TestInRegularAndScriptAsync(
input,
@"class C
{
void M()
......@@ -1043,6 +1112,51 @@ public D(int v)
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestWithBaseDelegatingConstructor2_NoFields()
{
await TestInRegularAndScriptAsync(
@"class C
{
void M()
{
new [|D|](1);
}
}
class B
{
private B(int x)
{
}
}
class D : B
{
}",
@"class C
{
void M()
{
new D(1);
}
}
class B
{
private B(int x)
{
}
}
class D : B
{
public D(int v)
{
}
}", index: 1);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestStructInLocalInitializerWithSystemType()
{
......@@ -1297,6 +1411,56 @@ public Delta(string v1, int v2, bool v) : this(v1, v2)
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestDelegateToSmallerConstructor1_NoFields()
{
await TestInRegularAndScriptAsync(
@"class A
{
void M()
{
Delta d1 = new Delta(""ss"", 3);
Delta d2 = new [|Delta|](""ss"", 5, true);
}
}
class Delta
{
private string v1;
private int v2;
public Delta(string v1, int v2)
{
this.v1 = v1;
this.v2 = v2;
}
}",
@"class A
{
void M()
{
Delta d1 = new Delta(""ss"", 3);
Delta d2 = new Delta(""ss"", 5, true);
}
}
class Delta
{
private string v1;
private int v2;
public Delta(string v1, int v2)
{
this.v1 = v1;
this.v2 = v2;
}
public Delta(string v1, int v2, bool v) : this(v1, v2)
{
}
}", index: 1);
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestDelegateToSmallerConstructor2()
{
......@@ -1486,6 +1650,28 @@ public C(int v)
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestGenerateFromThisInitializer1_NoFields()
{
await TestInRegularAndScriptAsync(
@"class C
{
public C() [|: this(4)|]
{
}
}",
@"class C
{
public C() : this(4)
{
}
public C(int v)
{
}
}", index: 1);
}
[Fact, WorkItem(910589, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/910589"), Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestGenerateFromThisInitializer2()
{
......@@ -1631,6 +1817,38 @@ public A(object t1, object t2)
}");
}
[WorkItem(539972, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539972")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestUnavailableTypeParameters_NoFields()
{
await TestInRegularAndScriptAsync(
@"class C<T1, T2>
{
public void Foo(T1 t1, T2 t2)
{
A a = new [|A|](t1, t2);
}
}
internal class A
{
}",
@"class C<T1, T2>
{
public void Foo(T1 t1, T2 t2)
{
A a = new A(t1, t2);
}
}
internal class A
{
public A(object t1, object t2)
{
}
}", index: 1);
}
[WorkItem(541020, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541020")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestGenerateCallToDefaultConstructorInStruct()
......@@ -1808,6 +2026,38 @@ class D
}");
}
[WorkItem(530003, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530003")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestAttributesWithArgument_NoFields()
{
await TestInRegularAndScriptAsync(
@"using System;
[AttributeUsage(AttributeTargets.Class)]
class MyAttribute : Attribute
{
}
[[|MyAttribute(123)|]]
class D
{
}",
@"using System;
[AttributeUsage(AttributeTargets.Class)]
class MyAttribute : Attribute
{
public MyAttribute(int v)
{
}
}
[MyAttribute(123)]
class D
{
}", index: 1);
}
[WorkItem(530003, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530003")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateConstructor)]
public async Task TestAttributesWithMultipleArguments()
......
......@@ -1314,6 +1314,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Generate constructor in &apos;{0}&apos; (without fields).
/// </summary>
internal static string Generate_constructor_in_0_without_fields {
get {
return ResourceManager.GetString("Generate_constructor_in_0_without_fields", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Generate delegating constructor &apos;{0}({1})&apos;.
/// </summary>
......
......@@ -1292,4 +1292,7 @@ This version used in: {2}</value>
<data name="Move_declaration_near_reference" xml:space="preserve">
<value>Move declaration near reference</value>
</data>
<data name="Generate_constructor_in_0_without_fields" xml:space="preserve">
<value>Generate constructor in '{0}' (without fields)</value>
</data>
</root>
\ No newline at end of file
......@@ -10,6 +10,7 @@
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.GenerateConstructorFromMembers
{
......@@ -55,7 +56,7 @@ protected override async Task<Document> GetChangedDocumentAsync(CancellationToke
var preferThrowExpression = options.GetOption(CodeStyleOptions.PreferThrowExpression).Value;
var compilation = await _document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var members = factory.CreateFieldDelegatingConstructor(
var (fields, constructor) = factory.CreateFieldDelegatingConstructor(
compilation,
_state.ContainingType.Name,
_state.ContainingType,
......@@ -77,7 +78,7 @@ protected override async Task<Document> GetChangedDocumentAsync(CancellationToke
var result = await CodeGenerator.AddMemberDeclarationsAsync(
_document.Project.Solution,
_state.ContainingType,
members,
fields.Concat(constructor),
new CodeGenerationOptions(
contextLocation: syntaxTree.GetLocation(_state.TextSpan),
afterThisLocation: afterThisLocation),
......
......@@ -10,35 +10,40 @@ internal abstract partial class AbstractGenerateConstructorService<TService, TAr
{
private class GenerateConstructorCodeAction : CodeAction
{
private readonly State _state;
private readonly Document _document;
private readonly TService _service;
private readonly Document _document;
private readonly State _state;
private readonly bool _withFields;
public GenerateConstructorCodeAction(
TService service,
Document document,
State state)
State state,
bool withFields)
{
_service = service;
_document = document;
_state = state;
_withFields = withFields;
}
protected override async Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
{
var result = await GetEditAsync(cancellationToken).ConfigureAwait(false);
return result.document;
}
public async Task<(Document document, bool addedFields)> GetEditAsync(CancellationToken cancellationToken)
{
var semanticDocument = await SemanticDocument.CreateAsync(_document, cancellationToken).ConfigureAwait(false);
var editor = new Editor(_service, semanticDocument, _state, cancellationToken);
var editor = new Editor(_service, semanticDocument, _state, _withFields, cancellationToken);
return await editor.GetEditAsync().ConfigureAwait(false);
}
public override string Title
{
get
{
return string.Format(FeaturesResources.Generate_constructor_in_0,
_state.TypeToGenerateIn.Name);
}
}
=> _withFields
? string.Format(FeaturesResources.Generate_constructor_in_0, _state.TypeToGenerateIn.Name)
: string.Format(FeaturesResources.Generate_constructor_in_0_without_fields, _state.TypeToGenerateIn.Name);
}
}
}
......@@ -28,21 +28,24 @@ private partial class Editor
private readonly TService _service;
private readonly SemanticDocument _document;
private readonly State _state;
private readonly bool _withFields;
private readonly CancellationToken _cancellationToken;
public Editor(
TService service,
SemanticDocument document,
State state,
bool withFields,
CancellationToken cancellationToken)
{
_service = service;
_document = document;
_state = state;
_withFields = withFields;
_cancellationToken = cancellationToken;
}
internal async Task<Document> GetEditAsync()
internal async Task<(Document, bool addedFields)> GetEditAsync()
{
// See if there's an accessible base constructor that would accept these
// types, then just call into that instead of generating fields.
......@@ -50,54 +53,58 @@ internal async Task<Document> GetEditAsync()
// then, see if there are any constructors that would take the first 'n' arguments
// we've provided. If so, delegate to those, and then create a field for any
// remaining arguments. Try to match from largest to smallest.
//
var edit = await GenerateThisOrBaseDelegatingConstructorAsync().ConfigureAwait(false);
if (edit.document != null)
{
return edit;
}
// Otherwise, just generate a normal constructor that assigns any provided
// parameters into fields.
return await GenerateThisOrBaseDelegatingConstructorAsync().ConfigureAwait(false) ??
await GenerateFieldDelegatingConstructorAsync().ConfigureAwait(false);
return await GenerateFieldDelegatingConstructorAsync().ConfigureAwait(false);
}
private async Task<Document> GenerateThisOrBaseDelegatingConstructorAsync()
private async Task<(Document document, bool addedFields)> GenerateThisOrBaseDelegatingConstructorAsync()
{
// We don't have to deal with the zero length case, since there's nothing to
// delegate. It will fall out of the GenerateFieldDelegatingConstructor above.
for (int i = _state.Arguments.Length; i >= 1; i--)
{
var edit = await GenerateThisOrBaseDelegatingConstructorAsync(i).ConfigureAwait(false);
if (edit != null)
if (edit.document != null)
{
return edit;
}
}
return null;
return default;
}
private async Task<Document> GenerateThisOrBaseDelegatingConstructorAsync(int argumentCount)
private async Task<(Document document, bool addedFields)> GenerateThisOrBaseDelegatingConstructorAsync(int argumentCount)
{
Document edit;
if ((edit = await GenerateDelegatingConstructorAsync(argumentCount, _state.TypeToGenerateIn).ConfigureAwait(false)) != null ||
(edit = await GenerateDelegatingConstructorAsync(argumentCount, _state.TypeToGenerateIn.BaseType).ConfigureAwait(false)) != null)
(Document document, bool addedField) edit;
if ((edit = await GenerateDelegatingConstructorAsync(argumentCount, _state.TypeToGenerateIn).ConfigureAwait(false)).document != null ||
(edit = await GenerateDelegatingConstructorAsync(argumentCount, _state.TypeToGenerateIn.BaseType).ConfigureAwait(false)).document != null)
{
return edit;
}
return null;
return default;
}
private async Task<Document> GenerateDelegatingConstructorAsync(
private async Task<(Document, bool addedFields)> GenerateDelegatingConstructorAsync(
int argumentCount,
INamedTypeSymbol namedType)
{
if (namedType == null)
{
return null;
return default;
}
// We can't resolve overloads across language.
if (_document.Project.Language != namedType.Language)
{
return null;
return default;
}
var arguments = _state.Arguments.Take(argumentCount).ToList();
......@@ -110,13 +117,13 @@ private async Task<Document> GenerateThisOrBaseDelegatingConstructorAsync(int ar
var instanceConstructors = namedType.InstanceConstructors.Where(IsSymbolAccessible).ToSet();
if (instanceConstructors.IsEmpty())
{
return null;
return default;
}
var delegatedConstructor = _service.GetDelegatingConstructor(_state, _document, argumentCount, namedType, instanceConstructors, _cancellationToken);
if (delegatedConstructor == null)
{
return null;
return default;
}
// There was a best match. Call it directly.
......@@ -138,16 +145,19 @@ private async Task<Document> GenerateThisOrBaseDelegatingConstructorAsync(int ar
// Can't generate the constructor if the parameter names we're copying over forcibly
// conflict with any names we generated.
if (delegatedConstructor.Parameters.Select(p => p.Name)
.Intersect(remainingParameterNames.Select(n => n.BestNameForParameter)).Any())
.Intersect(remainingParameterNames.Select(n => n.BestNameForParameter)).Any())
{
return null;
return default;
}
// Try to map those parameters to fields.
this.GetParameters(remainingArguments, remainingAttributeArguments,
remainingParameterTypes, remainingParameterNames,
out var parameterToExistingFieldMap, out var parameterToNewFieldMap, out var remainingParameters);
var fields = syntaxFactory.CreateFieldsForParameters(remainingParameters, parameterToNewFieldMap);
var fields = _withFields
? syntaxFactory.CreateFieldsForParameters(remainingParameters, parameterToNewFieldMap)
: ImmutableArray<IFieldSymbol>.Empty;
var assignStatements = syntaxFactory.CreateAssignmentStatements(
_document.SemanticModel.Compilation, remainingParameters,
parameterToExistingFieldMap, parameterToNewFieldMap,
......@@ -170,7 +180,7 @@ private async Task<Document> GenerateThisOrBaseDelegatingConstructorAsync(int ar
baseConstructorArguments: baseConstructorArguments,
thisConstructorArguments: thisConstructorArguments);
var members = new List<ISymbol>(fields) { constructor };
var members = fields.OfType<ISymbol>().Concat(constructor);
var result = await codeGenerationService.AddMembersAsync(
_document.Project.Solution,
_state.TypeToGenerateIn,
......@@ -179,16 +189,17 @@ private async Task<Document> GenerateThisOrBaseDelegatingConstructorAsync(int ar
_cancellationToken)
.ConfigureAwait(false);
return result;
return (result, fields.Length > 0);
}
private async Task<Document> GenerateFieldDelegatingConstructorAsync()
private async Task<(Document, bool addedFields)> GenerateFieldDelegatingConstructorAsync()
{
var arguments = _state.Arguments;
var parameterTypes = _state.ParameterTypes;
var typeParametersNames = _state.TypeToGenerateIn.GetAllTypeParameters().Select(t => t.Name).ToImmutableArray();
var parameterNames = GetParameterNames(arguments, typeParametersNames);
GetParameters(arguments, _state.AttributeArguments, parameterTypes, parameterNames,
out var parameterToExistingFieldMap, out var parameterToNewFieldMap, out var parameters);
......@@ -197,7 +208,7 @@ private async Task<Document> GenerateFieldDelegatingConstructorAsync()
var codeGenerationService = provider.GetService<ICodeGenerationService>();
var syntaxTree = _document.SyntaxTree;
var members = syntaxFactory.CreateFieldDelegatingConstructor(
var (fields, constructor) = syntaxFactory.CreateFieldDelegatingConstructor(
_document.SemanticModel.Compilation,
_state.TypeToGenerateIn.Name,
_state.TypeToGenerateIn, parameters,
......@@ -208,12 +219,12 @@ private async Task<Document> GenerateFieldDelegatingConstructorAsync()
var result = await codeGenerationService.AddMembersAsync(
_document.Project.Solution,
_state.TypeToGenerateIn,
members,
fields.Concat(constructor),
new CodeGenerationOptions(_state.Token.GetLocation()),
_cancellationToken)
.ConfigureAwait(false);
return result;
return (result, fields.Length > 0);
}
private ImmutableArray<ParameterName> GetParameterNames(
......@@ -242,13 +253,14 @@ private async Task<Document> GenerateFieldDelegatingConstructorAsync()
// See if there's a matching field we can use. First test in a case sensitive
// manner, then case insensitively.
if (!TryFindMatchingField(
arguments, attributeArguments, parameterNames, parameterTypes, i, parameterToExistingFieldMap,
arguments, attributeArguments, parameterNames, parameterTypes, i, parameterToExistingFieldMap,
parameterToNewFieldMap, caseSensitive: true, newParameterNames: out parameterNames))
{
if (!TryFindMatchingField(arguments, attributeArguments, parameterNames, parameterTypes, i, parameterToExistingFieldMap,
if (!TryFindMatchingField(
arguments, attributeArguments, parameterNames, parameterTypes, i, parameterToExistingFieldMap,
parameterToNewFieldMap, caseSensitive: false, newParameterNames: out parameterNames))
{
parameterToNewFieldMap[parameterNames[i].BestNameForParameter] =
parameterToNewFieldMap[parameterNames[i].BestNameForParameter] =
parameterNames[i].NameBasedOnArgument;
}
}
......@@ -261,6 +273,11 @@ private async Task<Document> GenerateFieldDelegatingConstructorAsync()
name: parameterNames[i].BestNameForParameter));
}
if (!_withFields)
{
parameterToNewFieldMap.Clear();
}
parameters = result.ToImmutableAndFree();
}
......
......@@ -6,6 +6,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Utilities;
using Roslyn.Utilities;
......@@ -46,18 +47,27 @@ public async Task<ImmutableArray<CodeAction>> GenerateConstructorAsync(Document
var semanticDocument = await SemanticDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false);
var state = await State.GenerateAsync((TService)this, semanticDocument, node, cancellationToken).ConfigureAwait(false);
if (state == null)
if (state != null)
{
return ImmutableArray<CodeAction>.Empty;
}
var result = ArrayBuilder<CodeAction>.GetInstance();
var codeAction = new GenerateConstructorCodeAction((TService)this, document, state, withFields: true);
result.Add(codeAction);
// First see the type of edit our regular code action would create. If it
// creates fields, then also offer to perform the code action without creating
// any fields.
var edit = await codeAction.GetEditAsync(cancellationToken).ConfigureAwait(false);
if (edit.addedFields)
{
result.Add(
new GenerateConstructorCodeAction((TService)this, document, state, withFields: false));
}
return GetActions(document, state);
return result.ToImmutableAndFree();
}
}
}
private ImmutableArray<CodeAction> GetActions(Document document, State state)
{
return ImmutableArray.Create<CodeAction>(new GenerateConstructorCodeAction((TService)this, document, state));
return ImmutableArray<CodeAction>.Empty;
}
protected static bool IsSymbolAccessible(
......
......@@ -242,12 +242,14 @@ private void AddProperties(ArrayBuilder<ISymbol> members)
// Empty Constructor for Struct is not allowed
if (!(parameters.Count == 0 && options != null && (options.TypeKind == TypeKind.Struct || options.TypeKind == TypeKind.Structure)))
{
members.AddRange(factory.CreateFieldDelegatingConstructor(
var (fields, constructor) = factory.CreateFieldDelegatingConstructor(
_document.SemanticModel.Compilation,
DetermineName(), null, parameters.ToImmutable(),
parameterToExistingFieldMap, parameterToNewFieldMap,
DetermineName(), null, parameters.ToImmutable(),
parameterToExistingFieldMap, parameterToNewFieldMap,
addNullChecks: false, preferThrowExpression: false,
cancellationToken: _cancellationToken));
cancellationToken: _cancellationToken);
members.AddRange(fields);
members.Add(constructor);
}
parameters.Free();
......
......@@ -63,7 +63,7 @@ internal static partial class ICodeDefinitionFactoryExtensions
: factory.CreateArguments(constructor.Parameters));
}
public static IEnumerable<ISymbol> CreateFieldDelegatingConstructor(
public static (ImmutableArray<ISymbol> fields, ISymbol constructor) CreateFieldDelegatingConstructor(
this SyntaxGenerator factory,
Compilation compilation,
string typeName,
......@@ -81,12 +81,7 @@ internal static partial class ICodeDefinitionFactoryExtensions
addNullChecks, preferThrowExpression).SelectAsArray(
s => s.WithAdditionalAnnotations(Simplifier.Annotation));
foreach (var field in fields)
{
yield return field;
}
yield return CodeGenerationSymbolFactory.CreateConstructorSymbol(
var constructor = CodeGenerationSymbolFactory.CreateConstructorSymbol(
attributes: default,
accessibility: Accessibility.Public,
modifiers: new DeclarationModifiers(),
......@@ -94,6 +89,8 @@ internal static partial class ICodeDefinitionFactoryExtensions
parameters: parameters,
statements: statements,
thisConstructorArguments: GetThisConstructorArguments(containingTypeOpt, parameterToExistingFieldMap));
return (ImmutableArray<ISymbol>.CastUp(fields), constructor);
}
private static ImmutableArray<SyntaxNode> GetThisConstructorArguments(
......@@ -122,11 +119,12 @@ internal static partial class ICodeDefinitionFactoryExtensions
return default;
}
public static IEnumerable<IFieldSymbol> CreateFieldsForParameters(
public static ImmutableArray<IFieldSymbol> CreateFieldsForParameters(
this SyntaxGenerator factory,
IList<IParameterSymbol> parameters,
IDictionary<string, string> parameterToNewFieldMap)
{
var result = ArrayBuilder<IFieldSymbol>.GetInstance();
foreach (var parameter in parameters)
{
var refKind = parameter.RefKind;
......@@ -139,15 +137,17 @@ internal static partial class ICodeDefinitionFactoryExtensions
// TODO: I'm not sure that's what we really want for ref parameters.
if (TryGetValue(parameterToNewFieldMap, parameterName, out var fieldName))
{
yield return CodeGenerationSymbolFactory.CreateFieldSymbol(
result.Add(CodeGenerationSymbolFactory.CreateFieldSymbol(
attributes: default,
accessibility: Accessibility.Private,
modifiers: default,
type: parameterType,
name: parameterToNewFieldMap[parameterName]);
name: parameterToNewFieldMap[parameterName]));
}
}
}
return result.ToImmutableAndFree();
}
private static bool TryGetValue(IDictionary<string, string> dictionary, string key, out string value)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册