Skip to content

Commit 9ad71ab

Browse files
committed
Merge pull request dotnet#208 from srivatsn/fixvar
Fixing a bug in the Provide Explicit type rule where it was trying to…
2 parents 6a40c02 + 9ee7fb2 commit 9ad71ab

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

src/Microsoft.DotNet.CodeFormatter.Analyzers.Tests/ProvideExplicitVariableTypeAnalyzerTests.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,49 @@ void M()
299299
Verify(input, expected, runFormatter: false);
300300
}
301301

302+
[Fact]
303+
public void TestDeclarationWithAnonymousTypeArguments()
304+
{
305+
const string input = @"
306+
using System.Linq;
307+
308+
class C1
309+
{
310+
void M()
311+
{
312+
// The variable names if of type IEnumerable<some_anonymous_type>. It is not itself of anonymous type,
313+
// but it has a type parameter of anonymous type.
314+
var names = from i in new [] { 1, 2, 3 }
315+
select new { Number = i, Age = i };
316+
317+
foreach (var name in names)
318+
{ }
319+
}
320+
}";
321+
const string expected = input;
322+
Verify(input, expected, runFormatter: false);
323+
}
324+
325+
[Fact]
326+
public void TestForEachWithErrorType()
327+
{
328+
const string input = @"
329+
class C1
330+
{
331+
void M()
332+
{
333+
// names will have error type here because System.Linq isn't included.
334+
var names = from i in new [] { 1, 2, 3 }
335+
select new { Number = i, Age = i };
336+
337+
foreach (var name in names)
338+
{ }
339+
}
340+
}";
341+
const string expected = input;
342+
Verify(input, expected, runFormatter: false);
343+
}
344+
302345
[Fact]
303346
public void TestVarDeclarationInUsing()
304347
{

src/Microsoft.DotNet.CodeFormatter.Analyzers/ProvideExplicitVariableTypeAnalyzer.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public override void Initialize(AnalysisContext context)
8484
node.Type.IsVar &&
8585
!IsTypeObvious(node) &&
8686
!IsAnonymousType(node, model, token)&&
87-
!HasErrors(node.Expression, model, token))
87+
!HasErrors(node, model, token))
8888
{
8989
syntaxContext.ReportDiagnostic(Diagnostic.Create(s_ruleForEachStatement, node.Identifier.GetLocation(), node.Identifier.Text));
9090
}
@@ -112,8 +112,11 @@ private static bool RuleEnabled(SyntaxNodeAnalysisContext syntaxContext)
112112
private static bool IsAnonymousType(SyntaxNode node, SemanticModel model, CancellationToken cancellationToken)
113113
{
114114
ISymbol symbol = model.GetDeclaredSymbol(node, cancellationToken);
115-
bool? isAnonymousType = ((ILocalSymbol)symbol)?.Type?.IsAnonymousType;
116-
return isAnonymousType.HasValue && isAnonymousType.Value;
115+
ITypeSymbol type = ((ILocalSymbol)symbol)?.Type;
116+
bool? isAnonymousType = type?.IsAnonymousType;
117+
bool? containsAnonymousTypeArguments = (type as INamedTypeSymbol)?.TypeArguments.Any(t => t.IsAnonymousType);
118+
return (isAnonymousType.HasValue && isAnonymousType.Value) ||
119+
(containsAnonymousTypeArguments.HasValue && containsAnonymousTypeArguments.Value);
117120
}
118121

119122
/// <summary>

0 commit comments

Comments
 (0)