Skip to content

Commit ab87232

Browse files
pgovindPrashanth Govindarajanbuyaa-n
authored
VB support for the virtual methods in DetectPreviewFeatureAnalyzer (#5566)
* First cut of message and URL support. Needs to be cleaned up * GeneralPreviewFeatureAttributeRule and unit test changes * ImplementsPreviewInterfaceRule and unit test changes * UsesPreviewTypeParameterRule and unit test changes * Everything else * Clean up * Fix test failures in PCA * Self review + unit tests * Make method static * First cut of addressing comments * Before reordering args * Checkpoint * All unit tests pass * MInor cleanup * More cleanup * Before unit test regex changes * Bug fix and all unit tests pass * sq * sq * Address comments * sq * pack * Flush out VB implementation for the virtual methods * Fix BC42030 warning * Improve test coverage * Add more test and fix a bug found * Apply feedbacks * Add seperate test for case sensitivity Co-authored-by: Prashanth Govindarajan <[email protected]> Co-authored-by: Buyaa Namnan <[email protected]>
1 parent 23fab74 commit ab87232

File tree

9 files changed

+802
-7
lines changed

9 files changed

+802
-7
lines changed

src/NetAnalyzers/CSharp/Microsoft.NetCore.Analyzers/Runtime/CSharpDetectPreviewFeatureAnalyzer.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,14 @@ private static bool TryGetConstraintClauseNode(SyntaxList<TypeParameterConstrain
257257
return ret;
258258
}
259259
}
260+
else if (typeSymbolDefinition is InterfaceDeclarationSyntax interfaceDeclaration)
261+
{
262+
SeparatedSyntaxList<BaseTypeSyntax> baseListTypes = interfaceDeclaration.BaseList.Types;
263+
if (TryGetPreviewInterfaceNodeForClassOrStructImplementingPreviewInterface(baseListTypes, previewInterfaceSymbol, out ret))
264+
{
265+
return ret;
266+
}
267+
}
260268
}
261269

262270
return ret;
@@ -294,5 +302,10 @@ private static bool TryGetPreviewInterfaceNodeForClassOrStructImplementingPrevie
294302

295303
private static bool IsIdentifierNameSyntax(TypeSyntax identifier, ISymbol previewInterfaceSymbol) => identifier is IdentifierNameSyntax identifierName && IsSyntaxToken(identifierName.Identifier, previewInterfaceSymbol) ||
296304
identifier is NullableTypeSyntax nullable && IsIdentifierNameSyntax(nullable.ElementType, previewInterfaceSymbol);
305+
306+
protected override SyntaxNode? GetPreviewImplementsClauseSyntaxNodeForMethodOrProperty(ISymbol methodSymbol, ISymbol previewSymbol)
307+
{
308+
throw new System.NotImplementedException();
309+
}
297310
}
298311
}

src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureAnalyzer.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ public abstract class DetectPreviewFeatureAnalyzer : DiagnosticAnalyzer
220220

221221
protected abstract SyntaxNode? GetPreviewSyntaxNodeForFieldsOrEvents(ISymbol fieldOrEventSymbol, ISymbol previewSymbol);
222222

223+
protected abstract SyntaxNode? GetPreviewImplementsClauseSyntaxNodeForMethodOrProperty(ISymbol methodOrPropertySymbol, ISymbol previewSymbol);
224+
223225
public override void Initialize(AnalysisContext context)
224226
{
225227
context.EnableConcurrentExecution();
@@ -573,7 +575,23 @@ private void ProcessPropertyOrMethodAttributes(SymbolAnalysisContext context,
573575
if (SymbolIsAnnotatedAsPreview(baseInterfaceMember, requiresPreviewFeaturesSymbols, previewFeatureAttributeSymbol))
574576
{
575577
string baseInterfaceMemberName = baseInterfaceMember.ContainingSymbol != null ? baseInterfaceMember.ContainingSymbol.Name + "." + baseInterfaceMember.Name : baseInterfaceMember.Name;
576-
ReportDiagnosticWithCustomMessageIfItExists(context, baseInterfaceMember, propertyOrMethodSymbol, requiresPreviewFeaturesSymbols, ImplementsPreviewMethodRule, ImplementsPreviewMethodRuleWithCustomMessage, propertyOrMethodSymbol.Name, baseInterfaceMemberName);
578+
SyntaxNode? previewImplementsClause = null;
579+
580+
if (propertyOrMethodSymbol.Language is LanguageNames.VisualBasic)
581+
{
582+
previewImplementsClause = GetPreviewImplementsClauseSyntaxNodeForMethodOrProperty(propertyOrMethodSymbol, baseInterfaceMember);
583+
}
584+
585+
if (previewImplementsClause != null)
586+
{
587+
ReportDiagnosticWithCustomMessageIfItExists(context, previewImplementsClause, baseInterfaceMember, requiresPreviewFeaturesSymbols,
588+
ImplementsPreviewMethodRule, ImplementsPreviewMethodRuleWithCustomMessage, propertyOrMethodSymbol.Name, baseInterfaceMemberName);
589+
}
590+
else
591+
{
592+
ReportDiagnosticWithCustomMessageIfItExists(context, baseInterfaceMember, propertyOrMethodSymbol, requiresPreviewFeaturesSymbols,
593+
ImplementsPreviewMethodRule, ImplementsPreviewMethodRuleWithCustomMessage, propertyOrMethodSymbol.Name, baseInterfaceMemberName);
594+
}
577595
}
578596
}
579597

src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureTests.Classes.cs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
66
Microsoft.NetCore.CSharp.Analyzers.Runtime.CSharpDetectPreviewFeatureAnalyzer,
77
Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
8+
using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier<
9+
Microsoft.NetCore.VisualBasic.Analyzers.Runtime.BasicDetectPreviewFeatureAnalyzer,
10+
Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
811

912
namespace Microsoft.NetCore.Analyzers.Runtime.UnitTests
1013
{
@@ -37,7 +40,7 @@ public abstract class BAbstract : IZoo
3740
{
3841
}
3942
40-
interface {|#0:IZoo|} : IFoo
43+
interface IZoo : {|#0:IFoo|}
4144
{
4245
bool Bar() { return true; }
4346
}
@@ -319,6 +322,40 @@ public abstract class AbClass
319322
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewMethodRule).WithLocation(1).WithArguments("Foo", "IFoo.Foo", DetectPreviewFeatureAnalyzer.DefaultURL));
320323
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.DerivesFromPreviewClassRule).WithLocation(2).WithArguments("Zoo", "AbClass", DetectPreviewFeatureAnalyzer.DefaultURL));
321324
await test.RunAsync();
325+
326+
var vbInput = @"
327+
Imports System.Runtime.Versioning
328+
Imports System
329+
Imports System.Collections.Generic
330+
331+
Namespace Preview_Feature_Scratch
332+
Public Partial Class Zoo
333+
Implements NonPreviewInterface, {|#0:PreviewInterface|}
334+
335+
Private _field As List(Of {|#1:PreviewType|})
336+
End Class
337+
338+
Public Partial Class Zoo
339+
Inherits {|#2:PreviewType|}
340+
End Class
341+
342+
<RequiresPreviewFeatures>
343+
Interface PreviewInterface
344+
End Interface
345+
346+
Interface NonPreviewInterface
347+
End Interface
348+
349+
<RequiresPreviewFeatures>
350+
Public MustInherit Class PreviewType
351+
End Class
352+
End Namespace
353+
";
354+
var vbTest = TestVB(vbInput);
355+
vbTest.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewInterfaceRule).WithLocation(0).WithArguments("Zoo", "PreviewInterface", DetectPreviewFeatureAnalyzer.DefaultURL));
356+
vbTest.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.FieldOrEventIsPreviewTypeRule).WithLocation(1).WithArguments("_field", "PreviewType", DetectPreviewFeatureAnalyzer.DefaultURL));
357+
vbTest.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.DerivesFromPreviewClassRule).WithLocation(2).WithArguments("Zoo", "PreviewType", DetectPreviewFeatureAnalyzer.DefaultURL));
358+
await vbTest.RunAsync();
322359
}
323360
}
324361
}

src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureTests.Fields.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
66
Microsoft.NetCore.CSharp.Analyzers.Runtime.CSharpDetectPreviewFeatureAnalyzer,
77
Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
8+
using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier<
9+
Microsoft.NetCore.VisualBasic.Analyzers.Runtime.BasicDetectPreviewFeatureAnalyzer,
10+
Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
811

912
namespace Microsoft.NetCore.Analyzers.Runtime.UnitTests
1013
{
@@ -105,6 +108,32 @@ class AGenericClass<T>
105108
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.GeneralPreviewFeatureAttributeRule).WithLocation(1).WithArguments("PreviewType", DetectPreviewFeatureAnalyzer.DefaultURL));
106109
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.FieldOrEventIsPreviewTypeRule).WithLocation(2).WithArguments("_genericPreviewField", "PreviewType", DetectPreviewFeatureAnalyzer.DefaultURL));
107110
await test.RunAsync();
111+
112+
var vbInput = @"
113+
Imports System
114+
Imports System.Runtime.Versioning
115+
Imports System.Collections.Generic
116+
Module Preview_Feature_Scratch
117+
Public Class Program
118+
Private _field As {|#0:PreviewType|}
119+
Private _genericPreviewField As AGenericClass(Of {|#2:PreviewType|})
120+
Private _noDiagnosticField As AGenericClass(Of Boolean)
121+
End Class
122+
123+
<RequiresPreviewFeatures>
124+
Public Class PreviewType
125+
End Class
126+
127+
Public Class AGenericClass(Of T)
128+
End Class
129+
130+
End Module
131+
";
132+
133+
var testVb = TestVB(vbInput);
134+
testVb.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.FieldOrEventIsPreviewTypeRule).WithLocation(0).WithArguments("_field", "PreviewType", DetectPreviewFeatureAnalyzer.DefaultURL));
135+
testVb.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.FieldOrEventIsPreviewTypeRule).WithLocation(2).WithArguments("_genericPreviewField", "PreviewType", DetectPreviewFeatureAnalyzer.DefaultURL));
136+
await testVb.RunAsync();
108137
}
109138

110139
[Fact]
@@ -212,6 +241,39 @@ public class AGenericClass<T>
212241
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.FieldOrEventIsPreviewTypeRule).WithLocation(2).WithArguments("_genericPreviewField", "PreviewType", DetectPreviewFeatureAnalyzer.DefaultURL));
213242
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.FieldOrEventIsPreviewTypeRule).WithLocation(3).WithArguments("_genericPreviewField", "AGenericClass", DetectPreviewFeatureAnalyzer.DefaultURL));
214243
await test.RunAsync();
244+
245+
var vbInput = @"
246+
Imports System.Runtime.Versioning
247+
Imports System
248+
249+
Namespace Preview_Feature_Scratch
250+
Public Class Program
251+
Private _field As {|#0:PreviewType|}
252+
Private _genericPreviewField As {|#3:AGenericClass(Of {|#2:PreviewType|})|}()
253+
254+
Public Sub New()
255+
_field = {|#1:New PreviewType()|}
256+
End Sub
257+
258+
Private Shared Sub Main(ByVal args As String())
259+
End Sub
260+
End Class
261+
262+
<RequiresPreviewFeatures>
263+
Public Class PreviewType
264+
End Class
265+
266+
<RequiresPreviewFeatures>
267+
Public Class AGenericClass(Of T As PreviewType)
268+
End Class
269+
End Namespace";
270+
271+
var vbTest = TestVB(vbInput);
272+
vbTest.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.FieldOrEventIsPreviewTypeRule).WithLocation(0).WithArguments("_field", "PreviewType", DetectPreviewFeatureAnalyzer.DefaultURL));
273+
vbTest.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.GeneralPreviewFeatureAttributeRule).WithLocation(1).WithArguments("PreviewType", DetectPreviewFeatureAnalyzer.DefaultURL));
274+
vbTest.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.FieldOrEventIsPreviewTypeRule).WithLocation(2).WithArguments("_genericPreviewField", "PreviewType", DetectPreviewFeatureAnalyzer.DefaultURL));
275+
vbTest.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.FieldOrEventIsPreviewTypeRule).WithLocation(3).WithArguments("_genericPreviewField", "AGenericClass", DetectPreviewFeatureAnalyzer.DefaultURL));
276+
await vbTest.RunAsync();
215277
}
216278

217279
[Fact]

src/NetAnalyzers/UnitTests/Microsoft.NetCore.Analyzers/Runtime/DetectPreviewFeatureTests.Interfaces.cs

Lines changed: 107 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
66
Microsoft.NetCore.CSharp.Analyzers.Runtime.CSharpDetectPreviewFeatureAnalyzer,
77
Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
8+
using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier<
9+
Microsoft.NetCore.VisualBasic.Analyzers.Runtime.BasicDetectPreviewFeatureAnalyzer,
10+
Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
811

912
namespace Microsoft.NetCore.Analyzers.Runtime.UnitTests
1013
{
@@ -37,12 +40,38 @@ public interface IProgram
3740
void MarkedMethodInInterface();
3841
}
3942
}
40-
4143
";
4244

4345
var test = TestCS(csInput);
4446
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewMethodRule).WithLocation(0).WithArguments("MarkedMethodInInterface", "IProgram.MarkedMethodInInterface", DetectPreviewFeatureAnalyzer.DefaultURL));
4547
await test.RunAsync();
48+
49+
var vbInput = @"
50+
Imports System.Runtime.Versioning
51+
Imports System
52+
53+
Namespace Preview_Feature_Scratch
54+
Class Program
55+
Implements IProgram
56+
57+
Private Shared Sub Main(ByVal args As String())
58+
Dim prog = New Program()
59+
End Sub
60+
61+
Public Sub MarkedMethodInInterface() Implements IProgram.{|#0:MarkedMethodInInterface|}
62+
Throw New NotImplementedException()
63+
End Sub
64+
End Class
65+
66+
Interface IProgram
67+
<RequiresPreviewFeatures>
68+
Sub MarkedMethodInInterface()
69+
End Interface
70+
End Namespace";
71+
72+
var testVb = TestVB(vbInput);
73+
testVb.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewMethodRule).WithLocation(0).WithArguments("MarkedMethodInInterface", "IProgram.MarkedMethodInInterface", DetectPreviewFeatureAnalyzer.DefaultURL));
74+
await testVb.RunAsync();
4675
}
4776

4877
[Fact]
@@ -61,7 +90,6 @@ static void Main(string[] args)
6190
}
6291
6392
public void {|#0:UnmarkedMethodInMarkedInterface|}() { }
64-
6593
}
6694
6795
[RequiresPreviewFeatures]
@@ -70,13 +98,48 @@ public interface IProgram
7098
public void UnmarkedMethodInMarkedInterface() { }
7199
}
72100
}
73-
74101
";
75102

76103
var test = TestCS(csInput);
77104
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewMethodRule).WithLocation(0).WithArguments("UnmarkedMethodInMarkedInterface", "IProgram.UnmarkedMethodInMarkedInterface", DetectPreviewFeatureAnalyzer.DefaultURL));
78105
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewInterfaceRule).WithLocation(1).WithArguments("Program", "IProgram", DetectPreviewFeatureAnalyzer.DefaultURL));
79106
await test.RunAsync();
107+
108+
var vbInput = @"
109+
Imports System
110+
Imports System.Runtime.Versioning
111+
Module Preview_Feature_Scratch
112+
Public Class Program
113+
Implements {|#1:IProgram|}
114+
Private Shared Sub Main(ByVal args As String())
115+
Dim prog = New Program()
116+
End Sub
117+
118+
Public Sub MarkedMethodInInterface() Implements IProgram.{|#0:MarkedMethodInInterface|}
119+
Throw New NotImplementedException()
120+
End Sub
121+
122+
Public ReadOnly Property Value As String Implements IProgram.{|#2:Value|}
123+
{|#3:Get|}
124+
Return """"
125+
End Get
126+
End Property
127+
End Class
128+
129+
<RequiresPreviewFeatures>
130+
Public Interface IProgram
131+
Sub MarkedMethodInInterface()
132+
ReadOnly Property Value() As String
133+
End Interface
134+
End Module
135+
";
136+
137+
var testVb = TestVB(vbInput);
138+
testVb.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewMethodRule).WithLocation(0).WithArguments("MarkedMethodInInterface", "IProgram.MarkedMethodInInterface", DetectPreviewFeatureAnalyzer.DefaultURL));
139+
testVb.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewInterfaceRule).WithLocation(1).WithArguments("Program", "IProgram", DetectPreviewFeatureAnalyzer.DefaultURL));
140+
testVb.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewMethodRule).WithLocation(2).WithArguments("Value", "IProgram.Value", DetectPreviewFeatureAnalyzer.DefaultURL));
141+
testVb.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewMethodRule).WithLocation(3).WithArguments("get_Value", "IProgram.get_Value", DetectPreviewFeatureAnalyzer.DefaultURL));
142+
await testVb.RunAsync();
80143
}
81144

82145
[Fact]
@@ -100,12 +163,32 @@ public interface IProgram
100163
{
101164
}
102165
}
103-
104166
";
105167

106168
var test = TestCS(csInput);
107169
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewInterfaceRule).WithLocation(0).WithArguments("Program", "IProgram", DetectPreviewFeatureAnalyzer.DefaultURL));
108170
await test.RunAsync();
171+
172+
var vbInput = @"
173+
Imports System
174+
Imports System.Runtime.Versioning
175+
Module Preview_Feature_Scratch
176+
Public Class Program
177+
Implements {|#1:IProgram|}
178+
Private Shared Sub Main(ByVal args As String())
179+
Dim prog = New Program()
180+
End Sub
181+
End Class
182+
183+
<RequiresPreviewFeatures>
184+
Public Interface IProgram
185+
End Interface
186+
End Module
187+
";
188+
189+
var testVb = TestVB(vbInput);
190+
testVb.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewInterfaceRule).WithLocation(1).WithArguments("Program", "IProgram", DetectPreviewFeatureAnalyzer.DefaultURL));
191+
await testVb.RunAsync();
109192
}
110193

111194
[Fact]
@@ -116,7 +199,7 @@ public async Task TestDerivedInterface()
116199
namespace Preview_Feature_Scratch
117200
{
118201
119-
interface {|#0:IZoo|} : IFoo
202+
interface IZoo : {|#0:IFoo|}
120203
{
121204
}
122205
@@ -130,6 +213,25 @@ interface IFoo
130213
var test = TestCS(csInput);
131214
test.ExpectedDiagnostics.Add(VerifyCS.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewInterfaceRule).WithLocation(0).WithArguments("IZoo", "IFoo", DetectPreviewFeatureAnalyzer.DefaultURL));
132215
await test.RunAsync();
216+
217+
var vbInput = @"
218+
Imports System
219+
Imports System.Runtime.Versioning
220+
Module Preview_Feature_Scratch
221+
Public Interface IZoo
222+
Inherits {|#0:IFoo|}
223+
End Interface
224+
225+
<RequiresPreviewFeatures>
226+
Public Interface IFoo
227+
Sub Bar()
228+
End Interface
229+
End Module
230+
";
231+
232+
var testVb = TestVB(vbInput);
233+
testVb.ExpectedDiagnostics.Add(VerifyVB.Diagnostic(DetectPreviewFeatureAnalyzer.ImplementsPreviewInterfaceRule).WithLocation(0).WithArguments("IZoo", "IFoo", DetectPreviewFeatureAnalyzer.DefaultURL));
234+
await testVb.RunAsync();
133235
}
134236
}
135237
}

0 commit comments

Comments
 (0)