Skip to content

Instantly share code, notes, and snippets.

@Schandlich
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Schandlich/12fb8fbd4272f62a5bfc to your computer and use it in GitHub Desktop.
Save Schandlich/12fb8fbd4272f62a5bfc to your computer and use it in GitHub Desktop.
Rosyln Interface Name Checker
[ExportCodeFixProvider(DiagnosticAnalyzer.DiagnosticId, LanguageNames.CSharp)]
internal class CodeFixProvider : ICodeFixProvider
{
public IEnumerable<string> GetFixableDiagnosticIds()
{
return new[] { DiagnosticAnalyzer.DiagnosticId };
}
public async Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, TextSpan span, IEnumerable<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var diagnosticSpan = diagnostics.First().Location.SourceSpan;
var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<InterfaceDeclarationSyntax>().First();
return new[] { CodeAction.Create("Add proceeding \"I\"", c => AddPreceddingIAsync(document, declaration, c)) };
}
private async Task<Solution> AddPreceddingIAsync(Document document, InterfaceDeclarationSyntax interDec, CancellationToken cancellationToken)
{
var identifierToken = interDec.Identifier;
var newName = "I" + identifierToken.Text;
var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
var typeSymbol = semanticModel.GetDeclaredSymbol(interDec, cancellationToken);
var originalSolution = document.Project.Solution;
var optionSet = originalSolution.Workspace.GetOptions();
var newSolution = await Renamer.RenameSymbolAsync(document.Project.Solution, typeSymbol, newName, optionSet, cancellationToken).ConfigureAwait(false);
return newSolution;
}
}
[DiagnosticAnalyzer]
[ExportDiagnosticAnalyzer(DiagnosticId, LanguageNames.CSharp)]
public class DiagnosticAnalyzer : ISyntaxNodeAnalyzer<SyntaxKind>
{
internal const string DiagnosticId = "InterfacesMustStartWithAnI";
internal const string Description = "All interfaces must begin with an Uppercase \"I\".";
internal static readonly string MessageFormat = "Make sure that this interface begins with an uppercase \"I\".";
internal const string Category = "Naming";
internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Description, MessageFormat, Category, DiagnosticSeverity.Warning);
public ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get { return ImmutableArray.Create(Rule); }
}
public ImmutableArray<SyntaxKind> SyntaxKindsOfInterest
{
get { return ImmutableArray.Create(SyntaxKind.InterfaceDeclaration); }
}
public void AnalyzeNode(SyntaxNode node, SemanticModel semanticModel, Action<Diagnostic> addDiagnostic, CancellationToken cancellationToken)
{
var interfaceNode = (InterfaceDeclarationSyntax)node;
var interfaceName = interfaceNode.Identifier.Text;
if (!interfaceName.StartsWith("I", StringComparison.Ordinal) ||
(interfaceName.StartsWith("I", StringComparison.Ordinal) && interfaceName.Length > 1 && interfaceName.Substring(1,1).ToLower() == interfaceName.Substring(1, 1)))
{
addDiagnostic(Diagnostic.Create(Rule, interfaceNode.GetLocation()));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment