Skip to content

Commit f9f07b7

Browse files
authored
dotnet-svcutil: add escaped prefix to types named with specific keywords (#5494)
* dotnet-svcutil: add escaped prefix to types named with specific keywords * Address review feedback and update test. * Rebase and update file and class names.
1 parent fcd9124 commit f9f07b7

File tree

6 files changed

+605
-0
lines changed

6 files changed

+605
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Collections.Generic;
6+
using Microsoft.CodeDom;
7+
8+
namespace Microsoft.Tools.ServiceModel.Svcutil
9+
{
10+
internal class TypeNameFixup : CodeDomVisitor
11+
{
12+
//starting in c#11, types cannot be named as file/required/scoped, work around this by escaping with an @ prefix.
13+
//ref: https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/breaking-changes/compiler%20breaking%20changes%20-%20dotnet%207#types-cannot-be-named-file
14+
private readonly List<string> _reservedKeyword = new List<string>() { "file", "required", "scoped" };
15+
protected override void Visit(CodeCompileUnit cu)
16+
{
17+
foreach (CodeNamespace ns in cu.Namespaces)
18+
{
19+
foreach (CodeTypeDeclaration typeDeclaration in ns.Types)
20+
{
21+
// Process the top-level type declaration and its nested types
22+
ProcessTypeAndMembers(typeDeclaration);
23+
}
24+
}
25+
}
26+
27+
private void ProcessTypeAndMembers(CodeTypeDeclaration typeDeclaration)
28+
{
29+
if (_reservedKeyword.Contains(typeDeclaration.Name))
30+
{
31+
typeDeclaration.Name = "@" + typeDeclaration.Name;
32+
}
33+
34+
foreach (CodeTypeMember member in typeDeclaration.Members)
35+
{
36+
if (member is CodeTypeDeclaration nestedType)
37+
{
38+
// Recursively process the nested type
39+
ProcessTypeAndMembers(nestedType);
40+
}
41+
}
42+
}
43+
}
44+
}

src/dotnet-svcutil/lib/src/CodeDomFixup/VisitorFixup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ private static CodeDomVisitor[] GetVisitors(ServiceContractGenerator generator,
2626
new EnsureAdditionalAssemblyReference(),
2727
new CreateCallbackImpl((generator.Options & ServiceContractGenerationOptions.TaskBasedAsynchronousMethod) == ServiceContractGenerationOptions.TaskBasedAsynchronousMethod, generator),
2828
new AddAsyncOpenClose(options), // this one need to run after CreateCallbakImpl which provide name of VerifyCallbackEvents method
29+
new TypeNameFixup()
2930
};
3031

3132
if (options.Sync != true)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
namespace ContractTypeNamedReservedKeyword_NS
11+
{
12+
using System.Runtime.Serialization;
13+
14+
15+
[System.Diagnostics.DebuggerStepThroughAttribute()]
16+
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
17+
[System.Runtime.Serialization.DataContractAttribute(Name="Composite", Namespace="http://schemas.datacontract.org/2004/07/WcfService1")]
18+
public partial class Composite : object
19+
{
20+
21+
private bool BoolValueField;
22+
23+
private ContractTypeNamedReservedKeyword_NS.Composite.file NestedClassValueField;
24+
25+
private string StringValueField;
26+
27+
[System.Runtime.Serialization.DataMemberAttribute()]
28+
public bool BoolValue
29+
{
30+
get
31+
{
32+
return this.BoolValueField;
33+
}
34+
set
35+
{
36+
this.BoolValueField = value;
37+
}
38+
}
39+
40+
[System.Runtime.Serialization.DataMemberAttribute()]
41+
public ContractTypeNamedReservedKeyword_NS.Composite.file NestedClassValue
42+
{
43+
get
44+
{
45+
return this.NestedClassValueField;
46+
}
47+
set
48+
{
49+
this.NestedClassValueField = value;
50+
}
51+
}
52+
53+
[System.Runtime.Serialization.DataMemberAttribute()]
54+
public string StringValue
55+
{
56+
get
57+
{
58+
return this.StringValueField;
59+
}
60+
set
61+
{
62+
this.StringValueField = value;
63+
}
64+
}
65+
66+
[System.Diagnostics.DebuggerStepThroughAttribute()]
67+
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
68+
[System.Runtime.Serialization.DataContractAttribute(Name="Composite.file", Namespace="http://schemas.datacontract.org/2004/07/WcfService1")]
69+
public partial class @file : object
70+
{
71+
72+
private string NestedClassStringField;
73+
74+
[System.Runtime.Serialization.DataMemberAttribute()]
75+
public string NestedClassString
76+
{
77+
get
78+
{
79+
return this.NestedClassStringField;
80+
}
81+
set
82+
{
83+
this.NestedClassStringField = value;
84+
}
85+
}
86+
}
87+
}
88+
89+
[System.Diagnostics.DebuggerStepThroughAttribute()]
90+
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
91+
[System.Runtime.Serialization.DataContractAttribute(Name="file", Namespace="http://schemas.datacontract.org/2004/07/WcfService1")]
92+
public partial class @file : object
93+
{
94+
95+
private bool BoolValueField;
96+
97+
private string StringValueField;
98+
99+
[System.Runtime.Serialization.DataMemberAttribute()]
100+
public bool BoolValue
101+
{
102+
get
103+
{
104+
return this.BoolValueField;
105+
}
106+
set
107+
{
108+
this.BoolValueField = value;
109+
}
110+
}
111+
112+
[System.Runtime.Serialization.DataMemberAttribute()]
113+
public string StringValue
114+
{
115+
get
116+
{
117+
return this.StringValueField;
118+
}
119+
set
120+
{
121+
this.StringValueField = value;
122+
}
123+
}
124+
}
125+
126+
[System.Diagnostics.DebuggerStepThroughAttribute()]
127+
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
128+
[System.Runtime.Serialization.DataContractAttribute(Name="scoped", Namespace="http://schemas.datacontract.org/2004/07/WcfService1")]
129+
public partial class @scoped : object
130+
{
131+
132+
private string scopeMemberField;
133+
134+
private ContractTypeNamedReservedKeyword_NS.required scopeRequiredMemberField;
135+
136+
[System.Runtime.Serialization.DataMemberAttribute()]
137+
public string scopeMember
138+
{
139+
get
140+
{
141+
return this.scopeMemberField;
142+
}
143+
set
144+
{
145+
this.scopeMemberField = value;
146+
}
147+
}
148+
149+
[System.Runtime.Serialization.DataMemberAttribute()]
150+
public ContractTypeNamedReservedKeyword_NS.required scopeRequiredMember
151+
{
152+
get
153+
{
154+
return this.scopeRequiredMemberField;
155+
}
156+
set
157+
{
158+
this.scopeRequiredMemberField = value;
159+
}
160+
}
161+
}
162+
163+
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
164+
[System.Runtime.Serialization.DataContractAttribute(Name="required", Namespace="http://schemas.datacontract.org/2004/07/WcfService1")]
165+
public enum @required : int
166+
{
167+
168+
[System.Runtime.Serialization.EnumMemberAttribute()]
169+
e1 = 0,
170+
171+
[System.Runtime.Serialization.EnumMemberAttribute()]
172+
e2 = 1,
173+
}
174+
175+
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
176+
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ContractTypeNamedReservedKeyword_NS.IService1")]
177+
public interface IService1
178+
{
179+
180+
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/GetData", ReplyAction="http://tempuri.org/IService1/GetDataResponse")]
181+
System.Threading.Tasks.Task<string> GetDataAsync(int value);
182+
183+
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/GetDataUsingDataContract1", ReplyAction="http://tempuri.org/IService1/GetDataUsingDataContract1Response")]
184+
System.Threading.Tasks.Task<ContractTypeNamedReservedKeyword_NS.Composite> GetDataUsingDataContract1Async(ContractTypeNamedReservedKeyword_NS.Composite c);
185+
186+
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/GetDataUsingDataContract2", ReplyAction="http://tempuri.org/IService1/GetDataUsingDataContract2Response")]
187+
System.Threading.Tasks.Task<ContractTypeNamedReservedKeyword_NS.file> GetDataUsingDataContract2Async(ContractTypeNamedReservedKeyword_NS.file f);
188+
189+
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/GetDataUsingDataContract3", ReplyAction="http://tempuri.org/IService1/GetDataUsingDataContract3Response")]
190+
System.Threading.Tasks.Task<ContractTypeNamedReservedKeyword_NS.required> GetDataUsingDataContract3Async(ContractTypeNamedReservedKeyword_NS.scoped s);
191+
}
192+
193+
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
194+
public interface IService1Channel : ContractTypeNamedReservedKeyword_NS.IService1, System.ServiceModel.IClientChannel
195+
{
196+
}
197+
198+
[System.Diagnostics.DebuggerStepThroughAttribute()]
199+
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
200+
public partial class Service1Client : System.ServiceModel.ClientBase<ContractTypeNamedReservedKeyword_NS.IService1>, ContractTypeNamedReservedKeyword_NS.IService1
201+
{
202+
203+
/// <summary>
204+
/// Implement this partial method to configure the service endpoint.
205+
/// </summary>
206+
/// <param name="serviceEndpoint">The endpoint to configure</param>
207+
/// <param name="clientCredentials">The client credentials</param>
208+
static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
209+
210+
public Service1Client() :
211+
base(Service1Client.GetDefaultBinding(), Service1Client.GetDefaultEndpointAddress())
212+
{
213+
this.Endpoint.Name = EndpointConfiguration.BasicHttpBinding_IService1.ToString();
214+
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
215+
}
216+
217+
public Service1Client(EndpointConfiguration endpointConfiguration) :
218+
base(Service1Client.GetBindingForEndpoint(endpointConfiguration), Service1Client.GetEndpointAddress(endpointConfiguration))
219+
{
220+
this.Endpoint.Name = endpointConfiguration.ToString();
221+
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
222+
}
223+
224+
public Service1Client(EndpointConfiguration endpointConfiguration, string remoteAddress) :
225+
base(Service1Client.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
226+
{
227+
this.Endpoint.Name = endpointConfiguration.ToString();
228+
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
229+
}
230+
231+
public Service1Client(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) :
232+
base(Service1Client.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
233+
{
234+
this.Endpoint.Name = endpointConfiguration.ToString();
235+
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
236+
}
237+
238+
public Service1Client(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
239+
base(binding, remoteAddress)
240+
{
241+
}
242+
243+
public System.Threading.Tasks.Task<string> GetDataAsync(int value)
244+
{
245+
return base.Channel.GetDataAsync(value);
246+
}
247+
248+
public System.Threading.Tasks.Task<ContractTypeNamedReservedKeyword_NS.Composite> GetDataUsingDataContract1Async(ContractTypeNamedReservedKeyword_NS.Composite c)
249+
{
250+
return base.Channel.GetDataUsingDataContract1Async(c);
251+
}
252+
253+
public System.Threading.Tasks.Task<ContractTypeNamedReservedKeyword_NS.file> GetDataUsingDataContract2Async(ContractTypeNamedReservedKeyword_NS.file f)
254+
{
255+
return base.Channel.GetDataUsingDataContract2Async(f);
256+
}
257+
258+
public System.Threading.Tasks.Task<ContractTypeNamedReservedKeyword_NS.required> GetDataUsingDataContract3Async(ContractTypeNamedReservedKeyword_NS.scoped s)
259+
{
260+
return base.Channel.GetDataUsingDataContract3Async(s);
261+
}
262+
263+
public virtual System.Threading.Tasks.Task OpenAsync()
264+
{
265+
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
266+
}
267+
268+
private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
269+
{
270+
if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IService1))
271+
{
272+
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
273+
result.MaxBufferSize = int.MaxValue;
274+
result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
275+
result.MaxReceivedMessageSize = int.MaxValue;
276+
result.AllowCookies = true;
277+
return result;
278+
}
279+
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
280+
}
281+
282+
private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
283+
{
284+
if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IService1))
285+
{
286+
return new System.ServiceModel.EndpointAddress("http://localhost:58413/Service1.svc");
287+
}
288+
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
289+
}
290+
291+
private static System.ServiceModel.Channels.Binding GetDefaultBinding()
292+
{
293+
return Service1Client.GetBindingForEndpoint(EndpointConfiguration.BasicHttpBinding_IService1);
294+
}
295+
296+
private static System.ServiceModel.EndpointAddress GetDefaultEndpointAddress()
297+
{
298+
return Service1Client.GetEndpointAddress(EndpointConfiguration.BasicHttpBinding_IService1);
299+
}
300+
301+
public enum EndpointConfiguration
302+
{
303+
304+
BasicHttpBinding_IService1,
305+
}
306+
}
307+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"providerId": "Microsoft.Tools.ServiceModel.Svcutil",
3+
"version": "99.99.99",
4+
"options": {
5+
"inputs": [
6+
"../../../../../src/dotnet-svcutil/lib/tests/TestCases/wsdl/TypeNameUseReservedKeyword.wsdl"
7+
],
8+
"namespaceMappings": [
9+
"*, ContractTypeNamedReservedKeyword_NS"
10+
],
11+
"outputFile": "Reference.cs",
12+
"targetFramework": "N.N",
13+
"typeReuseMode": "None"
14+
}
15+
}

0 commit comments

Comments
 (0)