Skip to content

Commit 574f7e7

Browse files
Merge remote-tracking branch 'upstream/main' into vbGenEquals
2 parents 94da14b + 07c890c commit 574f7e7

File tree

121 files changed

+1576
-1060
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+1576
-1060
lines changed

docs/Language Feature Status.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ efforts behind them.
2828
| [nameof accessing instance members](https://github.com/dotnet/roslyn/issues/40229) | main | [In Progress](https://github.com/dotnet/roslyn/pull/48754) | [YairHalberstadt ](https://github.com/YairHalberstadt) | [333fred](https://github.com/333fred), [AlekseyTs](https://github.com/AlekseyTs) | [333fred](https://github.com/333fred) |
2929
| [Utf8 String Literals](https://github.com/dotnet/csharplang/issues/184) | [Utf8StringLiterals](https://github.com/dotnet/roslyn/tree/features/Utf8StringLiterals) | [In Progress](https://github.com/dotnet/roslyn/issues/58848) | [AlekseyTs](https://github.com/AlekseyTs) | [cston](https://github.com/cston), [RikkiGibson](https://github.com/RikkiGibson) | [MadsTorgersen](https://github.com/MadsTorgersen) |
3030
| [ref fields](https://github.com/dotnet/csharplang/blob/main/proposals/low-level-struct-improvements.md) | TBD | [In Progress](https://github.com/dotnet/roslyn/issues/59194) | TBD | TBD | [jaredpar](https://github.com/jaredpar) |
31-
| [checked operators](https://github.com/dotnet/csharplang/issues/4665) | [CheckedUserDefinedOperators](https://github.com/dotnet/roslyn/tree/features/CheckedUserDefinedOperators) | [In Progress](https://github.com/dotnet/roslyn/issues/59458) | [AlekseyTs](https://github.com/AlekseyTs) | TBD | [AlekseyTs](https://github.com/AlekseyTs) |
31+
| [checked operators](https://github.com/dotnet/csharplang/issues/4665) | [CheckedUserDefinedOperators](https://github.com/dotnet/roslyn/tree/features/CheckedUserDefinedOperators) | [In Progress](https://github.com/dotnet/roslyn/issues/59458) | [AlekseyTs](https://github.com/AlekseyTs) | [333fred](https://github.com/333fred), [chsienki](https://github.com/chsienki) | [AlekseyTs](https://github.com/AlekseyTs) |
3232

3333
# C# 10.0
3434

eng/Versions.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
<MicrosoftDevDivOptimizationDataPowerShellVersion>1.0.339</MicrosoftDevDivOptimizationDataPowerShellVersion>
9292
<MicrosoftDiagnosticsRuntimeVersion>0.8.31-beta</MicrosoftDiagnosticsRuntimeVersion>
9393
<MicrosoftDiagnosticsTracingTraceEventVersion>1.0.35</MicrosoftDiagnosticsTracingTraceEventVersion>
94-
<MicrosoftDiaSymReaderVersion>1.4.0-beta2-21528-02</MicrosoftDiaSymReaderVersion>
94+
<MicrosoftDiaSymReaderVersion>1.4.0</MicrosoftDiaSymReaderVersion>
9595
<MicrosoftDiaSymReaderConverterVersion>1.1.0-beta2-21528-01</MicrosoftDiaSymReaderConverterVersion>
9696
<MicrosoftDiaSymReaderConverterXmlVersion>1.1.0-beta2-21528-01</MicrosoftDiaSymReaderConverterXmlVersion>
9797
<MicrosoftDiaSymReaderNativeVersion>17.0.0-beta1.21524.1</MicrosoftDiaSymReaderNativeVersion>

src/Analyzers/CSharp/Tests/MakeFieldReadonly/MakeFieldReadonlyTests.cs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,6 +1797,113 @@ public int Value
17971797
}
17981798
</Document>
17991799
</Project>
1800+
</Workspace>");
1801+
}
1802+
1803+
[WorkItem(40644, "https://github.com/dotnet/roslyn/issues/40644")]
1804+
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)]
1805+
public async Task ShouldNotWarnForDataMemberFieldsInDataContractClasses()
1806+
{
1807+
await TestMissingAsync(
1808+
@"
1809+
<Workspace>
1810+
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferencesNet45=""true"">
1811+
<Document>
1812+
[System.Runtime.Serialization.DataContractAttribute]
1813+
public class MyClass
1814+
{
1815+
[System.Runtime.Serialization.DataMember]
1816+
private bool [|isReadOnly|];
1817+
}
1818+
</Document>
1819+
</Project>
1820+
</Workspace>");
1821+
}
1822+
1823+
[WorkItem(40644, "https://github.com/dotnet/roslyn/issues/40644")]
1824+
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)]
1825+
public async Task ShouldWarnForDataMemberFieldsInNonDataContractClasses()
1826+
{
1827+
await TestInRegularAndScript1Async(
1828+
@"
1829+
<Workspace>
1830+
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferencesNet45=""true"">
1831+
<Document>
1832+
public class MyClass
1833+
{
1834+
[System.Runtime.Serialization.DataMember]
1835+
private bool [|isReadOnly|];
1836+
}
1837+
</Document>
1838+
</Project>
1839+
</Workspace>",
1840+
@"
1841+
<Workspace>
1842+
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferencesNet45=""true"">
1843+
<Document>
1844+
public class MyClass
1845+
{
1846+
[System.Runtime.Serialization.DataMember]
1847+
private readonly bool isReadOnly;
1848+
}
1849+
</Document>
1850+
</Project>
1851+
</Workspace>");
1852+
}
1853+
1854+
[WorkItem(40644, "https://github.com/dotnet/roslyn/issues/40644")]
1855+
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)]
1856+
public async Task ShouldWarnForPrivateNonDataMemberFieldsInDataContractClasses()
1857+
{
1858+
await TestInRegularAndScript1Async(
1859+
@"
1860+
<Workspace>
1861+
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferencesNet45=""true"">
1862+
<Document>
1863+
[System.Runtime.Serialization.DataContractAttribute]
1864+
public class MyClass
1865+
{
1866+
[System.Runtime.Serialization.DataMember]
1867+
private bool isReadOnly;
1868+
1869+
private bool [|isReadOnly2|];
1870+
}
1871+
</Document>
1872+
</Project>
1873+
</Workspace>",
1874+
@"
1875+
<Workspace>
1876+
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferencesNet45=""true"">
1877+
<Document>
1878+
[System.Runtime.Serialization.DataContractAttribute]
1879+
public class MyClass
1880+
{
1881+
[System.Runtime.Serialization.DataMember]
1882+
private bool isReadOnly;
1883+
1884+
private readonly bool isReadOnly2;
1885+
}
1886+
</Document>
1887+
</Project>
1888+
</Workspace>");
1889+
}
1890+
1891+
[WorkItem(40644, "https://github.com/dotnet/roslyn/issues/40644")]
1892+
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)]
1893+
public async Task ShouldNotWarnForPublicImplicitDataMemberFieldsInDataContractClasses()
1894+
{
1895+
await TestMissingAsync(
1896+
@"
1897+
<Workspace>
1898+
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferencesNet45=""true"">
1899+
<Document>
1900+
[System.Runtime.Serialization.DataContractAttribute]
1901+
public class MyClass
1902+
{
1903+
public bool [|isReadOnly|];
1904+
}
1905+
</Document>
1906+
</Project>
18001907
</Workspace>");
18011908
}
18021909
}

src/Analyzers/Core/Analyzers/MakeFieldReadonly/MakeFieldReadonlyDiagnosticAnalyzer.cs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ protected override void InitializeWorker(AnalysisContext context)
4444
var fieldStateMap = new ConcurrentDictionary<IFieldSymbol, (bool isCandidate, bool written)>();
4545

4646
var threadStaticAttribute = compilationStartContext.Compilation.ThreadStaticAttributeType();
47+
var dataContractAttribute = compilationStartContext.Compilation.DataContractAttribute();
48+
var dataMemberAttribute = compilationStartContext.Compilation.DataMemberAttribute();
4749

4850
// We register following actions in the compilation:
4951
// 1. A symbol action for field symbols to ensure the field state is initialized for every field in
@@ -111,7 +113,7 @@ void OnSymbolEnd(SymbolAnalysisContext symbolEndContext)
111113
}
112114
}
113115

114-
static bool IsCandidateField(IFieldSymbol symbol, INamedTypeSymbol threadStaticAttribute) =>
116+
static bool IsCandidateField(IFieldSymbol symbol, INamedTypeSymbol threadStaticAttribute, INamedTypeSymbol dataContractAttribute, INamedTypeSymbol dataMemberAttribute) =>
115117
symbol.DeclaredAccessibility == Accessibility.Private &&
116118
!symbol.IsReadOnly &&
117119
!symbol.IsConst &&
@@ -121,12 +123,22 @@ static bool IsCandidateField(IFieldSymbol symbol, INamedTypeSymbol threadStaticA
121123
!symbol.IsFixedSizeBuffer &&
122124
!symbol.GetAttributes().Any(
123125
static (a, threadStaticAttribute) => SymbolEqualityComparer.Default.Equals(a.AttributeClass, threadStaticAttribute),
124-
threadStaticAttribute);
126+
threadStaticAttribute) &&
127+
!IsDataContractSerializable(symbol, dataContractAttribute, dataMemberAttribute);
128+
129+
static bool IsDataContractSerializable(IFieldSymbol symbol, INamedTypeSymbol dataContractAttribute, INamedTypeSymbol dataMemberAttribute)
130+
{
131+
if (dataContractAttribute is null || dataMemberAttribute is null)
132+
return false;
133+
134+
return symbol.GetAttributes().Any(static (x, dataMemberAttribute) => SymbolEqualityComparer.Default.Equals(x.AttributeClass, dataMemberAttribute), dataMemberAttribute)
135+
&& symbol.ContainingType.GetAttributes().Any(static (x, dataContractAttribute) => SymbolEqualityComparer.Default.Equals(x.AttributeClass, dataContractAttribute), dataContractAttribute);
136+
}
125137

126138
// Method to update the field state for a candidate field written outside constructor and field initializer.
127139
void UpdateFieldStateOnWrite(IFieldSymbol field)
128140
{
129-
Debug.Assert(IsCandidateField(field, threadStaticAttribute));
141+
Debug.Assert(IsCandidateField(field, threadStaticAttribute, dataContractAttribute, dataMemberAttribute));
130142
Debug.Assert(fieldStateMap.ContainsKey(field));
131143

132144
fieldStateMap[field] = (isCandidate: true, written: true);
@@ -135,7 +147,7 @@ void UpdateFieldStateOnWrite(IFieldSymbol field)
135147
// Method to get or initialize the field state.
136148
(bool isCandidate, bool written) TryGetOrInitializeFieldState(IFieldSymbol fieldSymbol, AnalyzerOptions options, CancellationToken cancellationToken)
137149
{
138-
if (!IsCandidateField(fieldSymbol, threadStaticAttribute))
150+
if (!IsCandidateField(fieldSymbol, threadStaticAttribute, dataContractAttribute, dataMemberAttribute))
139151
{
140152
return default;
141153
}
@@ -145,14 +157,14 @@ void UpdateFieldStateOnWrite(IFieldSymbol field)
145157
return result;
146158
}
147159

148-
result = ComputeInitialFieldState(fieldSymbol, options, threadStaticAttribute, cancellationToken);
160+
result = ComputeInitialFieldState(fieldSymbol, options, threadStaticAttribute, dataContractAttribute, dataMemberAttribute, cancellationToken);
149161
return fieldStateMap.GetOrAdd(fieldSymbol, result);
150162
}
151163

152164
// Method to compute the initial field state.
153-
static (bool isCandidate, bool written) ComputeInitialFieldState(IFieldSymbol field, AnalyzerOptions options, INamedTypeSymbol threadStaticAttribute, CancellationToken cancellationToken)
165+
static (bool isCandidate, bool written) ComputeInitialFieldState(IFieldSymbol field, AnalyzerOptions options, INamedTypeSymbol threadStaticAttribute, INamedTypeSymbol dataContractAttribute, INamedTypeSymbol dataMemberAttribute, CancellationToken cancellationToken)
154166
{
155-
Debug.Assert(IsCandidateField(field, threadStaticAttribute));
167+
Debug.Assert(IsCandidateField(field, threadStaticAttribute, dataContractAttribute, dataMemberAttribute));
156168

157169
var option = GetCodeStyleOption(field, options, cancellationToken);
158170
if (option == null || !option.Value)

src/Analyzers/Core/Analyzers/UseSystemHashCode/Analyzer.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System;
56
using System.Collections.Generic;
67
using System.Collections.Immutable;
78
using System.Diagnostics.CodeAnalysis;
@@ -35,18 +36,18 @@ private Analyzer(
3536

3637
public static bool TryGetAnalyzer(Compilation compilation, [NotNullWhen(true)] out Analyzer analyzer)
3738
{
39+
analyzer = default;
3840
var objectType = compilation.GetSpecialType(SpecialType.System_Object);
3941
// This may not find anything. However, CanAnalyze checks for this. So
4042
// we represent the value as non-nullable for all future code.
41-
var objectGetHashCodeMethod = objectType?.GetMembers(nameof(GetHashCode)).FirstOrDefault() as IMethodSymbol;
42-
var equalityComparerType = compilation.GetTypeByMetadataName(typeof(EqualityComparer<>).FullName!);
43-
var systemHashCodeType = compilation.GetTypeByMetadataName("System.HashCode");
43+
var equalityComparerType = compilation.GetBestTypeByMetadataName(typeof(EqualityComparer<>).FullName!);
4444

45-
if (systemHashCodeType == null || objectGetHashCodeMethod == null)
46-
{
47-
analyzer = default;
45+
if (objectType?.GetMembers(nameof(GetHashCode)).FirstOrDefault() is not IMethodSymbol objectGetHashCodeMethod)
46+
return false;
47+
48+
var systemHashCodeType = compilation.GetBestTypeByMetadataName("System.HashCode");
49+
if (systemHashCodeType == null)
4850
return false;
49-
}
5051

5152
analyzer = new Analyzer(compilation, objectGetHashCodeMethod, equalityComparerType, systemHashCodeType);
5253
return true;

src/Analyzers/VisualBasic/Tests/MakeFieldReadonly/MakeFieldReadonlyTests.vb

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,5 +979,106 @@ Class C
979979
Private Shared [|t_obj|] As Object
980980
End Class")
981981
End Function
982+
983+
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)>
984+
<WorkItem(40644, "https://github.com/dotnet/roslyn/issues/40644")>
985+
Public Async Function ShouldNotWarnForDataMemberFieldsInDataContractClasses() As Task
986+
Dim initialMarkup =
987+
<Workspace>
988+
<Project Language="Visual Basic" CommonReferencesNet45="true">
989+
<Document>
990+
&lt;System.Runtime.Serialization.DataContract&gt;
991+
Class Test
992+
&lt;System.Runtime.Serialization.DataMember&gt;
993+
Private [|id|] As String
994+
End Class
995+
</Document>
996+
</Project>
997+
</Workspace>.ToString()
998+
999+
Await TestMissingAsync(initialMarkup)
1000+
End Function
1001+
1002+
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)>
1003+
<WorkItem(40644, "https://github.com/dotnet/roslyn/issues/40644")>
1004+
Public Async Function ShouldWarnForDataMemberFieldsInNonDataContractClasses() As Task
1005+
Dim initialMarkup =
1006+
<Workspace>
1007+
<Project Language="Visual Basic" CommonReferencesNet45="true">
1008+
<Document>
1009+
Class Test
1010+
&lt;System.Runtime.Serialization.DataMember&gt;
1011+
Private [|id|] As String
1012+
End Class
1013+
</Document>
1014+
</Project>
1015+
</Workspace>.ToString()
1016+
Dim expectedMarkup =
1017+
<Workspace>
1018+
<Project Language="Visual Basic" CommonReferencesNet45="true">
1019+
<Document>
1020+
Class Test
1021+
&lt;System.Runtime.Serialization.DataMember&gt;
1022+
Private ReadOnly id As String
1023+
End Class
1024+
</Document>
1025+
</Project>
1026+
</Workspace>.ToString()
1027+
1028+
Await TestInRegularAndScript1Async(initialMarkup, expectedMarkup)
1029+
End Function
1030+
1031+
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)>
1032+
<WorkItem(40644, "https://github.com/dotnet/roslyn/issues/40644")>
1033+
Public Async Function ShouldWarnForPrivateNonDataMemberFieldsInDataContractClasses() As Task
1034+
Dim initialMarkup =
1035+
<Workspace>
1036+
<Project Language="Visual Basic" CommonReferencesNet45="true">
1037+
<Document>
1038+
&lt;System.Runtime.Serialization.DataContract&gt;
1039+
Class Test
1040+
&lt;System.Runtime.Serialization.DataMember&gt;
1041+
Private id As String
1042+
1043+
Private [|id2|] As String
1044+
End Class
1045+
</Document>
1046+
</Project>
1047+
</Workspace>.ToString()
1048+
Dim expectedMarkup =
1049+
<Workspace>
1050+
<Project Language="Visual Basic" CommonReferencesNet45="true">
1051+
<Document>
1052+
&lt;System.Runtime.Serialization.DataContract&gt;
1053+
Class Test
1054+
&lt;System.Runtime.Serialization.DataMember&gt;
1055+
Private id As String
1056+
1057+
Private ReadOnly id2 As String
1058+
End Class
1059+
</Document>
1060+
</Project>
1061+
</Workspace>.ToString()
1062+
1063+
Await TestInRegularAndScript1Async(initialMarkup, expectedMarkup)
1064+
End Function
1065+
1066+
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)>
1067+
<WorkItem(40644, "https://github.com/dotnet/roslyn/issues/40644")>
1068+
Public Async Function ShouldNotWarnForPublicImplicitDataMemberFieldsInDataContractClasses() As Task
1069+
Dim initialMarkup =
1070+
<Workspace>
1071+
<Project Language="Visual Basic" CommonReferencesNet45="true">
1072+
<Document>
1073+
&lt;System.Runtime.Serialization.DataContract&gt;
1074+
Class Test
1075+
Public [|id|] As String
1076+
End Class
1077+
</Document>
1078+
</Project>
1079+
</Workspace>.ToString()
1080+
1081+
Await TestMissingAsync(initialMarkup)
1082+
End Function
9821083
End Class
9831084
End Namespace

src/Compilers/Core/CodeAnalysisTest/Analyzers/AnalyzerConfigTests.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2536,6 +2536,29 @@ public void EquivalentSourcePathNames(string sourcePath, bool shouldMatch)
25362536
}
25372537
}
25382538

2539+
2540+
[Fact]
2541+
public void CorrectlyMergeGlobalConfigWithEscapedPaths()
2542+
{
2543+
var configs = ArrayBuilder<AnalyzerConfig>.GetInstance();
2544+
configs.Add(Parse(@"
2545+
is_global = true
2546+
[/Test.cs]
2547+
a = a
2548+
[/\Test.cs]
2549+
b = b
2550+
", "/.editorconfig"));
2551+
2552+
var configSet = AnalyzerConfigSet.Create(configs, out var diagnostics);
2553+
configs.Free();
2554+
2555+
var options = configSet.GetOptionsForSourcePath("/Test.cs");
2556+
2557+
Assert.Equal(2, options.AnalyzerOptions.Count);
2558+
Assert.Equal("a", options.AnalyzerOptions["a"]);
2559+
Assert.Equal("b", options.AnalyzerOptions["b"]);
2560+
}
2561+
25392562
#endregion
25402563
}
25412564
}

src/Compilers/Core/Portable/CommandLine/AnalyzerConfig.SectionNameMatching.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public bool IsMatch(string s)
114114
numberRangePairs.ToImmutableAndFree());
115115
}
116116

117-
internal static bool TryUnescapeSectionName(string sectionName, out string? escapedSectionName)
117+
internal static string UnescapeSectionName(string sectionName)
118118
{
119119
var sb = new StringBuilder();
120120
SectionNameLexer lexer = new SectionNameLexer(sectionName);
@@ -125,9 +125,14 @@ internal static bool TryUnescapeSectionName(string sectionName, out string? esca
125125
{
126126
sb.Append(lexer.EatCurrentCharacter());
127127
}
128+
else
129+
{
130+
// We only call this on strings that were already passed through IsAbsoluteEditorConfigPath, so
131+
// we shouldn't have any other token kinds here.
132+
throw ExceptionUtilities.UnexpectedValue(tokenKind);
133+
}
128134
}
129-
escapedSectionName = sb.ToString();
130-
return true;
135+
return sb.ToString();
131136
}
132137

133138
/// <summary>

0 commit comments

Comments
 (0)