-
-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Created code analyzers to detect mistakes when defining font and colo…
…r providers.
- Loading branch information
Showing
31 changed files
with
1,587 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
...isualStudio.Toolkit.Analyzers/Analyzers/CVST006SpecifyFontAndColorProviderGuidAnalyzer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
|
||
namespace Community.VisualStudio.Toolkit.Analyzers | ||
{ | ||
/// <summary> | ||
/// Detects font and color providers without an explicit GUID. | ||
/// </summary> | ||
[DiagnosticAnalyzer(LanguageNames.CSharp)] | ||
public class CVST006SpecifyFontAndColorProviderGuidAnalyzer : MissingGuidAttributeAnalyzerBase | ||
{ | ||
internal const string DiagnosticId = Diagnostics.DefineExplicitGuidForFontAndColorProviders; | ||
|
||
private static readonly DiagnosticDescriptor _rule = new( | ||
DiagnosticId, | ||
GetLocalizableString(nameof(Resources.CVST006_Title)), | ||
GetLocalizableString(nameof(Resources.CVST006_MessageFormat)), | ||
"Usage", | ||
DiagnosticSeverity.Warning, | ||
isEnabledByDefault: true, | ||
description: GetLocalizableString(nameof(Resources.CVST006_Description))); | ||
|
||
protected override DiagnosticDescriptor Descriptor => _rule; | ||
|
||
protected override string BaseTypeName => KnownTypeNames.BaseFontAndColorProvider; | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
...udio.Toolkit.Analyzers/Analyzers/CVST006SpecifyFontAndColorProviderGuidCodeFixProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System.Collections.Immutable; | ||
using System.Composition; | ||
using Community.VisualStudio.Toolkit.Analyzers.Analyzers; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
|
||
namespace Community.VisualStudio.Toolkit.Analyzers | ||
{ | ||
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CVST006SpecifyFontAndColorProviderGuidCodeFixProvider))] | ||
[Shared] | ||
public class CVST006SpecifyFontAndColorProviderGuidCodeFixProvider : MissingGuidAttributeCodeFixProviderBase | ||
{ | ||
public sealed override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(CVST006SpecifyFontAndColorProviderGuidAnalyzer.DiagnosticId); | ||
|
||
protected override string Title => Resources.CVST006_CodeFix; | ||
|
||
protected override string EquivalenceKey => nameof(Resources.CVST006_CodeFix); | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
...isualStudio.Toolkit.Analyzers/Analyzers/CVST007SpecifyFontAndColorCategoryGuidAnalyzer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
|
||
namespace Community.VisualStudio.Toolkit.Analyzers | ||
{ | ||
/// <summary> | ||
/// Detects font and color categories without an explicit GUID. | ||
/// </summary> | ||
[DiagnosticAnalyzer(LanguageNames.CSharp)] | ||
public class CVST007SpecifyFontAndColorCategoryGuidAnalyzer : MissingGuidAttributeAnalyzerBase | ||
{ | ||
internal const string DiagnosticId = Diagnostics.DefineExplicitGuidForFontAndColorCategories; | ||
|
||
private static readonly DiagnosticDescriptor _rule = new( | ||
DiagnosticId, | ||
GetLocalizableString(nameof(Resources.CVST007_Title)), | ||
GetLocalizableString(nameof(Resources.CVST007_MessageFormat)), | ||
"Usage", | ||
DiagnosticSeverity.Warning, | ||
isEnabledByDefault: true, | ||
description: GetLocalizableString(nameof(Resources.CVST007_Description))); | ||
|
||
protected override DiagnosticDescriptor Descriptor => _rule; | ||
|
||
protected override string BaseTypeName => KnownTypeNames.BaseFontAndColorCategory; | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
...udio.Toolkit.Analyzers/Analyzers/CVST007SpecifyFontAndColorCategoryGuidCodeFixProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System.Collections.Immutable; | ||
using System.Composition; | ||
using Community.VisualStudio.Toolkit.Analyzers.Analyzers; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CodeFixes; | ||
|
||
namespace Community.VisualStudio.Toolkit.Analyzers | ||
{ | ||
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CVST007SpecifyFontAndColorCategoryGuidCodeFixProvider))] | ||
[Shared] | ||
public class CVST007SpecifyFontAndColorCategoryGuidCodeFixProvider : MissingGuidAttributeCodeFixProviderBase | ||
{ | ||
public sealed override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(CVST007SpecifyFontAndColorCategoryGuidAnalyzer.DiagnosticId); | ||
|
||
protected override string Title => Resources.CVST007_CodeFix; | ||
|
||
protected override string EquivalenceKey => nameof(Resources.CVST007_CodeFix); | ||
} | ||
} |
108 changes: 108 additions & 0 deletions
108
...udio.Toolkit.Analyzers/Analyzers/CVST008FontAndColorCategoryShouldHaveProviderAnalyzer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
using System.Collections.Concurrent; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
using System.Threading; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
|
||
namespace Community.VisualStudio.Toolkit.Analyzers | ||
{ | ||
/// <summary> | ||
/// Detects a missing font and color provider. | ||
/// </summary> | ||
[DiagnosticAnalyzer(LanguageNames.CSharp)] | ||
public class CVST008FontAndColorCategoryShouldHaveProviderAnalyzer : AnalyzerBase | ||
{ | ||
internal const string DiagnosticId = Diagnostics.DefineProviderForFontAndColorCategories; | ||
|
||
private static readonly DiagnosticDescriptor _rule = new( | ||
DiagnosticId, | ||
GetLocalizableString(nameof(Resources.CVST008_Title)), | ||
GetLocalizableString(nameof(Resources.CVST008_MessageFormat)), | ||
"Usage", | ||
DiagnosticSeverity.Warning, | ||
isEnabledByDefault: true, | ||
description: GetLocalizableString(nameof(Resources.CVST008_Description))); | ||
|
||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(_rule); | ||
|
||
public override void Initialize(AnalysisContext context) | ||
{ | ||
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); | ||
context.EnableConcurrentExecution(); | ||
|
||
context.RegisterCompilationStartAction(OnCompilationStart); | ||
} | ||
|
||
private static void OnCompilationStart(CompilationStartAnalysisContext context) | ||
{ | ||
INamedTypeSymbol baseFontAndColorProviderType; | ||
INamedTypeSymbol baseFontAndColorCategoryType; | ||
|
||
baseFontAndColorProviderType = context.Compilation.GetTypeByMetadataName(KnownTypeNames.BaseFontAndColorProvider); | ||
baseFontAndColorCategoryType = context.Compilation.GetTypeByMetadataName(KnownTypeNames.BaseFontAndColorCategory); | ||
|
||
if ((baseFontAndColorProviderType is not null) && (baseFontAndColorCategoryType is not null)) | ||
{ | ||
State state = new(baseFontAndColorProviderType, baseFontAndColorCategoryType); | ||
|
||
context.RegisterSyntaxNodeAction( | ||
(x) => RecordProvidersAndCategories(state, x), | ||
SyntaxKind.ClassDeclaration | ||
); | ||
|
||
context.RegisterCompilationEndAction((endContext) => | ||
{ | ||
if (state.Categories.Any() && !state.HasProviders) | ||
{ | ||
// There are categories but no providers. Add a diagnostic to each category. | ||
foreach (SyntaxToken token in state.Categories.Values) | ||
{ | ||
endContext.ReportDiagnostic(Diagnostic.Create(_rule, token.GetLocation())); | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
|
||
private static void RecordProvidersAndCategories(State state, SyntaxNodeAnalysisContext context) | ||
{ | ||
ClassDeclarationSyntax declaration = (ClassDeclarationSyntax)context.Node; | ||
INamedTypeSymbol classSymbol = context.SemanticModel.GetDeclaredSymbol(declaration, context.CancellationToken); | ||
|
||
if (classSymbol.IsSubclassOf(state.BaseFontAndColorProviderType)) | ||
{ | ||
state.HasProviders = true; | ||
} | ||
else if (classSymbol.IsSubclassOf(state.BaseFontAndColorCategoryType)) | ||
{ | ||
state.Categories[classSymbol] = declaration.Identifier; | ||
} | ||
} | ||
|
||
private class State | ||
{ | ||
private int _hasProviders; | ||
|
||
public State(INamedTypeSymbol baseFontAndColorProviderType, INamedTypeSymbol baseFontAndColorCategoryType) | ||
{ | ||
BaseFontAndColorProviderType = baseFontAndColorProviderType; | ||
BaseFontAndColorCategoryType = baseFontAndColorCategoryType; | ||
} | ||
|
||
public INamedTypeSymbol BaseFontAndColorProviderType { get; } | ||
|
||
public INamedTypeSymbol BaseFontAndColorCategoryType { get; } | ||
|
||
public ConcurrentDictionary<ISymbol, SyntaxToken> Categories { get; } = new(); | ||
|
||
public bool HasProviders | ||
{ | ||
get => Interlocked.CompareExchange(ref _hasProviders, 0, 0) != 0; | ||
set => Interlocked.Exchange(ref _hasProviders, value ? 1 : 0); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.