提交 c8d684d2 编写于 作者: J John Hamby

Moved system language analyzers to separate files.

上级 d70a522f
...@@ -34,13 +34,13 @@ void M1() ...@@ -34,13 +34,13 @@ void M1()
}"; }";
CreateCompilationWithMscorlib45(source) CreateCompilationWithMscorlib45(source)
.VerifyDiagnostics() .VerifyDiagnostics()
.VerifyAnalyzerDiagnostics(new DiagnosticAnalyzer[] { new EmptyArrayOperationAnalyzer() }, null, null, false, .VerifyAnalyzerDiagnostics(new DiagnosticAnalyzer[] { new EmptyArrayAnalyzer() }, null, null, false,
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "new int[0]").WithLocation(6, 22), Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "new int[0]").WithLocation(6, 22),
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "{ }").WithLocation(7, 23), Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "{ }").WithLocation(7, 23),
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "new C[] { }").WithLocation(8, 20), Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "new C[] { }").WithLocation(8, 20),
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "new int[0][]").WithLocation(12, 24), Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "new int[0][]").WithLocation(12, 24),
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "new int[0][][][]").WithLocation(13, 28), Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "new int[0][][][]").WithLocation(13, 28),
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "new int[0][,]").WithLocation(15, 26) Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "new int[0][,]").WithLocation(15, 26)
); );
} }
......
...@@ -29,9 +29,10 @@ ...@@ -29,9 +29,10 @@
<Compile Include="Collections\ByteSequenceComparerTests.cs" /> <Compile Include="Collections\ByteSequenceComparerTests.cs" />
<Compile Include="Diagnostics\BoxingOperationAnalyzer.cs" /> <Compile Include="Diagnostics\BoxingOperationAnalyzer.cs" />
<Compile Include="Diagnostics\DiagnosticLocalizationTests.cs" /> <Compile Include="Diagnostics\DiagnosticLocalizationTests.cs" />
<Compile Include="Diagnostics\EmptyArrayOperationAnalyzer.cs" /> <Compile Include="Diagnostics\EmptyArrayAnalyzer.cs" />
<Compile Include="Diagnostics\LocalCouldBeConstAnalyzer.cs" />
<Compile Include="Diagnostics\OperationTestAnalyzer.cs" /> <Compile Include="Diagnostics\OperationTestAnalyzer.cs" />
<Compile Include="Diagnostics\SystemLanguageAnalyzer.cs" /> <Compile Include="Diagnostics\FieldCouldBeReadOnlyAnalyzer.cs" />
<Compile Include="Emit\EmitOptionsTests.cs" /> <Compile Include="Emit\EmitOptionsTests.cs" />
<Compile Include="Emit\CustomDebugInfoTests.cs" /> <Compile Include="Emit\CustomDebugInfoTests.cs" />
<Compile Include="InternalUtilities\StreamExtensionsTests.cs" /> <Compile Include="InternalUtilities\StreamExtensionsTests.cs" />
...@@ -184,4 +185,4 @@ ...@@ -184,4 +185,4 @@
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" /> <Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\build\Targets\Roslyn.Toolsets.Xunit.targets" /> <Import Project="..\..\..\..\build\Targets\Roslyn.Toolsets.Xunit.targets" />
</ImportGroup> </ImportGroup>
</Project> </Project>
\ No newline at end of file
...@@ -5,13 +5,12 @@ ...@@ -5,13 +5,12 @@
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Semantics; using Microsoft.CodeAnalysis.Semantics;
namespace Microsoft.CodeAnalysis.UnitTests.Diagnostics namespace Microsoft.CodeAnalysis.UnitTests.Diagnostics.SystemLanguage
{ {
/// <summary>Base type for an analyzer that looks for empty array allocations and recommends their replacement.</summary> /// <summary>Analyzer that looks for empty array allocations and recommends their replacement.</summary>
public class EmptyArrayOperationAnalyzer : DiagnosticAnalyzer public class EmptyArrayAnalyzer : DiagnosticAnalyzer
{ {
/// <summary>Diagnostic category "Performance".</summary> private const string SystemCategory = "System";
private const string PerformanceCategory = "Performance";
/// <summary>The name of the array type.</summary> /// <summary>The name of the array type.</summary>
internal const string ArrayTypeName = "System.Array"; // using instead of GetSpecialType to make more testable internal const string ArrayTypeName = "System.Array"; // using instead of GetSpecialType to make more testable
...@@ -27,7 +26,7 @@ public class EmptyArrayOperationAnalyzer : DiagnosticAnalyzer ...@@ -27,7 +26,7 @@ public class EmptyArrayOperationAnalyzer : DiagnosticAnalyzer
"EmptyArrayRule", "EmptyArrayRule",
localizableTitle, localizableTitle,
localizableMessage, localizableMessage,
PerformanceCategory, SystemCategory,
DiagnosticSeverity.Warning, DiagnosticSeverity.Warning,
isEnabledByDefault: true); isEnabledByDefault: true);
......
...@@ -132,118 +132,4 @@ void Report(CompilationAnalysisContext context, IFieldSymbol field, DiagnosticDe ...@@ -132,118 +132,4 @@ void Report(CompilationAnalysisContext context, IFieldSymbol field, DiagnosticDe
context.ReportDiagnostic(Diagnostic.Create(descriptor, field.Locations.FirstOrDefault())); context.ReportDiagnostic(Diagnostic.Create(descriptor, field.Locations.FirstOrDefault()));
} }
} }
/// <summary>Analyzer used to identify local variables that could be declared Const.</summary>
public class LocalCouldBeConstAnalyzer : DiagnosticAnalyzer
{
private const string SystemCategory = "System";
public static readonly DiagnosticDescriptor LocalCouldBeConstDescriptor = new DiagnosticDescriptor(
"LocalCouldBeReadOnly",
"Local Could Be Const",
"Local variable is never modified and so could be const.",
SystemCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
/// <summary>Gets the set of supported diagnostic descriptors from this analyzer.</summary>
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get { return ImmutableArray.Create(LocalCouldBeConstDescriptor); }
}
public sealed override void Initialize(AnalysisContext context)
{
context.RegisterOperationBlockStartAction(
(operationBlockContext) =>
{
IMethodSymbol containingMethod = operationBlockContext.OwningSymbol as IMethodSymbol;
if (containingMethod != null)
{
HashSet<ILocalSymbol> mightBecomeConstLocals = new HashSet<ILocalSymbol>();
HashSet<ILocalSymbol> assignedToLocals = new HashSet<ILocalSymbol>();
operationBlockContext.RegisterOperationAction(
(operationContext) =>
{
IAssignmentExpression assignment = (IAssignmentExpression)operationContext.Operation;
AssignTo(assignment.Target, assignedToLocals, mightBecomeConstLocals);
},
OperationKind.AssignmentExpression,
OperationKind.CompoundAssignmentExpression,
OperationKind.IncrementExpression);
operationBlockContext.RegisterOperationAction(
(operationContext) =>
{
IInvocationExpression invocation = (IInvocationExpression)operationContext.Operation;
foreach (IArgument argument in invocation.ArgumentsInParameterOrder)
{
if (argument.Parameter.RefKind == RefKind.Out || argument.Parameter.RefKind == RefKind.Ref)
{
AssignTo(argument.Value, assignedToLocals, mightBecomeConstLocals);
}
}
},
OperationKind.InvocationExpression);
operationBlockContext.RegisterOperationAction(
(operationContext) =>
{
IVariableDeclarationStatement declaration = (IVariableDeclarationStatement)operationContext.Operation;
foreach (IVariable variable in declaration.Variables)
{
ILocalSymbol local = variable.Variable;
if (!local.IsConst)
{
var localType = local.Type;
if ((!localType.IsReferenceType || localType.SpecialType == SpecialType.System_String) && localType.SpecialType != SpecialType.None)
{
if (variable.InitialValue != null && variable.InitialValue.ConstantValue != null)
{
mightBecomeConstLocals.Add(local);
}
}
}
}
},
OperationKind.VariableDeclarationStatement);
operationBlockContext.RegisterOperationBlockEndAction(
(operationBlockEndContext) =>
{
foreach (ILocalSymbol couldBeConstLocal in mightBecomeConstLocals)
{
Report(operationBlockEndContext, couldBeConstLocal, LocalCouldBeConstDescriptor);
}
});
}
});
}
static void AssignTo(IExpression target, HashSet<ILocalSymbol> assignedToLocals, HashSet<ILocalSymbol> mightBecomeConstLocals)
{
if (target.Kind == OperationKind.LocalReferenceExpression)
{
ILocalSymbol targetLocal = ((ILocalReferenceExpression)target).Local;
assignedToLocals.Add(targetLocal);
mightBecomeConstLocals.Remove(targetLocal);
}
else if (target.Kind == OperationKind.FieldReferenceExpression)
{
IFieldReferenceExpression fieldReference = (IFieldReferenceExpression)target;
if (fieldReference.Instance != null && fieldReference.Instance.ResultType.IsValueType)
{
AssignTo(fieldReference.Instance, assignedToLocals, mightBecomeConstLocals);
}
}
}
void Report(OperationBlockAnalysisContext context, ILocalSymbol local, DiagnosticDescriptor descriptor)
{
context.ReportDiagnostic(Diagnostic.Create(descriptor, local.Locations.FirstOrDefault()));
}
}
} }
\ No newline at end of file
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Semantics;
namespace Microsoft.CodeAnalysis.UnitTests.Diagnostics.SystemLanguage
{
/// <summary>Analyzer used to identify local variables that could be declared Const.</summary>
public class LocalCouldBeConstAnalyzer : DiagnosticAnalyzer
{
private const string SystemCategory = "System";
public static readonly DiagnosticDescriptor LocalCouldBeConstDescriptor = new DiagnosticDescriptor(
"LocalCouldBeReadOnly",
"Local Could Be Const",
"Local variable is never modified and so could be const.",
SystemCategory,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
/// <summary>Gets the set of supported diagnostic descriptors from this analyzer.</summary>
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get { return ImmutableArray.Create(LocalCouldBeConstDescriptor); }
}
public sealed override void Initialize(AnalysisContext context)
{
context.RegisterOperationBlockStartAction(
(operationBlockContext) =>
{
IMethodSymbol containingMethod = operationBlockContext.OwningSymbol as IMethodSymbol;
if (containingMethod != null)
{
HashSet<ILocalSymbol> mightBecomeConstLocals = new HashSet<ILocalSymbol>();
HashSet<ILocalSymbol> assignedToLocals = new HashSet<ILocalSymbol>();
operationBlockContext.RegisterOperationAction(
(operationContext) =>
{
IAssignmentExpression assignment = (IAssignmentExpression)operationContext.Operation;
AssignTo(assignment.Target, assignedToLocals, mightBecomeConstLocals);
},
OperationKind.AssignmentExpression,
OperationKind.CompoundAssignmentExpression,
OperationKind.IncrementExpression);
operationBlockContext.RegisterOperationAction(
(operationContext) =>
{
IInvocationExpression invocation = (IInvocationExpression)operationContext.Operation;
foreach (IArgument argument in invocation.ArgumentsInParameterOrder)
{
if (argument.Parameter.RefKind == RefKind.Out || argument.Parameter.RefKind == RefKind.Ref)
{
AssignTo(argument.Value, assignedToLocals, mightBecomeConstLocals);
}
}
},
OperationKind.InvocationExpression);
operationBlockContext.RegisterOperationAction(
(operationContext) =>
{
IVariableDeclarationStatement declaration = (IVariableDeclarationStatement)operationContext.Operation;
foreach (IVariable variable in declaration.Variables)
{
ILocalSymbol local = variable.Variable;
if (!local.IsConst && !assignedToLocals.Contains(local))
{
var localType = local.Type;
if ((!localType.IsReferenceType || localType.SpecialType == SpecialType.System_String) && localType.SpecialType != SpecialType.None)
{
if (variable.InitialValue != null && variable.InitialValue.ConstantValue != null)
{
mightBecomeConstLocals.Add(local);
}
}
}
}
},
OperationKind.VariableDeclarationStatement);
operationBlockContext.RegisterOperationBlockEndAction(
(operationBlockEndContext) =>
{
foreach (ILocalSymbol couldBeConstLocal in mightBecomeConstLocals)
{
Report(operationBlockEndContext, couldBeConstLocal, LocalCouldBeConstDescriptor);
}
});
}
});
}
static void AssignTo(IExpression target, HashSet<ILocalSymbol> assignedToLocals, HashSet<ILocalSymbol> mightBecomeConstLocals)
{
if (target.Kind == OperationKind.LocalReferenceExpression)
{
ILocalSymbol targetLocal = ((ILocalReferenceExpression)target).Local;
assignedToLocals.Add(targetLocal);
mightBecomeConstLocals.Remove(targetLocal);
}
else if (target.Kind == OperationKind.FieldReferenceExpression)
{
IFieldReferenceExpression fieldReference = (IFieldReferenceExpression)target;
if (fieldReference.Instance != null && fieldReference.Instance.ResultType.IsValueType)
{
AssignTo(fieldReference.Instance, assignedToLocals, mightBecomeConstLocals);
}
}
}
void Report(OperationBlockAnalysisContext context, ILocalSymbol local, DiagnosticDescriptor descriptor)
{
context.ReportDiagnostic(Diagnostic.Create(descriptor, local.Locations.FirstOrDefault()));
}
}
}
\ No newline at end of file
...@@ -39,13 +39,13 @@ End Class ...@@ -39,13 +39,13 @@ End Class
Dim comp = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime(source) Dim comp = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime(source)
comp.VerifyDiagnostics() comp.VerifyDiagnostics()
comp.VerifyAnalyzerDiagnostics({New EmptyArrayOperationAnalyzer}, Nothing, Nothing, False, comp.VerifyAnalyzerDiagnostics({New EmptyArrayAnalyzer}, Nothing, Nothing, False,
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "New Integer(-1) { }").WithLocation(3, 33), Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "New Integer(-1) { }").WithLocation(3, 33),
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "{ }").WithLocation(4, 30), Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "{ }").WithLocation(4, 30),
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "New C(-1) { }").WithLocation(5, 27), Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "New C(-1) { }").WithLocation(5, 27),
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "New Integer(-1)() { }").WithLocation(9, 35), Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "New Integer(-1)() { }").WithLocation(9, 35),
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "New Integer( -1)()()() { }").WithLocation(10, 39), Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "New Integer( -1)()()() { }").WithLocation(10, 39),
Diagnostic(EmptyArrayOperationAnalyzer.UseArrayEmptyDescriptor.Id, "New Integer(-1)(,) { }").WithLocation(12, 37)) Diagnostic(EmptyArrayAnalyzer.UseArrayEmptyDescriptor.Id, "New Integer(-1)(,) { }").WithLocation(12, 37))
End Sub End Sub
<Fact> <Fact>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册