Skip to content

Commit

Permalink
Merge pull request #1 from sharwell/auto-gen-updates
Browse files Browse the repository at this point in the history
Auto generated code updates
  • Loading branch information
AArnott committed Apr 22, 2015
2 parents a70c9ff + c5b6bd2 commit d10db47
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 182 deletions.
145 changes: 2 additions & 143 deletions StyleCop.Analyzers/StyleCop.Analyzers/AnalyzerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,157 +6,16 @@
namespace StyleCop.Analyzers
{
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

internal static class AnalyzerExtensions
{
internal static SyntaxNode WithSameTriviaAs(this SyntaxNode target, SyntaxNode source)
{
if (target == null) throw new ArgumentNullException(nameof(target));
if (source == null) throw new ArgumentNullException(nameof(source));

return target
.WithLeadingTrivia(source.GetLeadingTrivia())
.WithTrailingTrivia(source.GetTrailingTrivia());
}

internal static T FirstAncestorOrSelfOfType<T>(this SyntaxNode node) where T : SyntaxNode =>
(T)node.FirstAncestorOrSelfOfType(typeof(T));

internal static SyntaxNode FirstAncestorOrSelfOfType(this SyntaxNode node, params Type[] types)
{
var currentNode = node;
while (true)
{
if (currentNode == null) break;
foreach (var type in types)
{
if (currentNode.GetType() == type) return currentNode;
}
currentNode = currentNode.Parent;
}
return null;
}

internal static T FirstAncestorOfType<T>(this SyntaxNode node) where T : SyntaxNode =>
(T)node.FirstAncestorOfType(typeof(T));

internal static SyntaxNode FirstAncestorOfType(this SyntaxNode node, params Type[] types)
{
var currentNode = node;
while (true)
{
var parent = currentNode.Parent;
if (parent == null) break;
foreach (var type in types)
{
if (parent.GetType() == type) return parent;
}
currentNode = parent;
}
return null;
}

internal static IList<IMethodSymbol> GetAllMethodsIncludingFromInnerTypes(this INamedTypeSymbol typeSymbol)
{
var methods = typeSymbol.GetMembers().OfType<IMethodSymbol>().ToList();
var innerTypes = typeSymbol.GetMembers().OfType<INamedTypeSymbol>();
foreach (var innerType in innerTypes)
{
methods.AddRange(innerType.GetAllMethodsIncludingFromInnerTypes());
}
return methods;
}

internal static IEnumerable<INamedTypeSymbol> AllBaseTypesAndSelf(this INamedTypeSymbol typeSymbol)
{
yield return typeSymbol;
foreach (var b in AllBaseTypes(typeSymbol))
yield return b;
}

internal static IEnumerable<INamedTypeSymbol> AllBaseTypes(this INamedTypeSymbol typeSymbol)
{
while (typeSymbol.BaseType != null)
{
yield return typeSymbol.BaseType;
typeSymbol = typeSymbol.BaseType;
}
}

internal static bool HasAttributeOnAncestorOrSelf(this SyntaxNode node, string attributeName)
{
var csharpNode = node as CSharpSyntaxNode;
if (csharpNode != null)
return csharpNode.HasAttributeOnAncestorOrSelf(attributeName);
return false;
}

internal static bool HasAttributeOnAncestorOrSelf(this SyntaxNode node, params string[] attributeNames)
{
var csharpNode = node as CSharpSyntaxNode;
if (csharpNode != null)
foreach (var attributeName in attributeNames)
if (csharpNode.HasAttributeOnAncestorOrSelf(attributeName)) return true;
return false;
}

internal static bool HasAttributeOnAncestorOrSelf(this CSharpSyntaxNode node, string attributeName)
{
var parentMethod = (BaseMethodDeclarationSyntax)node.FirstAncestorOrSelfOfType(typeof(MethodDeclarationSyntax), typeof(ConstructorDeclarationSyntax));
if (parentMethod?.AttributeLists.HasAttribute(attributeName) ?? false)
return true;
var type = (TypeDeclarationSyntax)node.FirstAncestorOrSelfOfType(typeof(ClassDeclarationSyntax), typeof(StructDeclarationSyntax));
while (type != null)
{
if (type.AttributeLists.HasAttribute(attributeName))
return true;
type = (TypeDeclarationSyntax)type.FirstAncestorOfType(typeof(ClassDeclarationSyntax), typeof(StructDeclarationSyntax));
}
var property = node.FirstAncestorOrSelfOfType<PropertyDeclarationSyntax>();
if (property?.AttributeLists.HasAttribute(attributeName) ?? false)
return true;
var accessor = node.FirstAncestorOrSelfOfType<AccessorDeclarationSyntax>();
if (accessor?.AttributeLists.HasAttribute(attributeName) ?? false)
return true;
var anInterface = node.FirstAncestorOrSelfOfType<InterfaceDeclarationSyntax>();
if (anInterface?.AttributeLists.HasAttribute(attributeName) ?? false)
return true;
var anEvent = node.FirstAncestorOrSelfOfType<EventDeclarationSyntax>();
if (anEvent?.AttributeLists.HasAttribute(attributeName) ?? false)
return true;
var anEnum = node.FirstAncestorOrSelfOfType<EnumDeclarationSyntax>();
if (anEnum?.AttributeLists.HasAttribute(attributeName) ?? false)
return true;
var field = node.FirstAncestorOrSelfOfType<FieldDeclarationSyntax>();
if (field?.AttributeLists.HasAttribute(attributeName) ?? false)
return true;
var eventField = node.FirstAncestorOrSelfOfType<EventFieldDeclarationSyntax>();
if (eventField?.AttributeLists.HasAttribute(attributeName) ?? false)
return true;
var parameter = node as ParameterSyntax;
if (parameter?.AttributeLists.HasAttribute(attributeName) ?? false)
return true;
var aDelegate = node as DelegateDeclarationSyntax;
if (aDelegate?.AttributeLists.HasAttribute(attributeName) ?? false)
return true;
return false;
}

internal static bool HasAttribute(this SyntaxList<AttributeListSyntax> attributeLists, string attributeName) =>
attributeLists.SelectMany(a => a.Attributes).Any(a => a.Name.ToString().EndsWith(attributeName, StringComparison.OrdinalIgnoreCase));

internal static void RegisterSyntaxTreeActionHonorExclusions(this AnalysisContext context, Action<SyntaxTreeAnalysisContext> action)
{
context.RegisterSyntaxTreeAction(
c =>
{
if (c.IsGeneratedDocument(c.CancellationToken))
if (c.IsGeneratedDocument())
{
return;
}
Expand All @@ -174,7 +33,7 @@ internal static void RegisterSyntaxNodeActionHonorExclusions<TLanguageKindEnum>(
context.RegisterSyntaxNodeAction(
c =>
{
if (c.IsGenerated(c.CancellationToken))
if (c.IsGenerated())
{
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,64 +30,37 @@ internal static class GeneratedCodeAnalysisExtensions
/// <summary>
/// Checks whether the given node or its containing document is auto generated by a tool.
/// </summary>
internal static bool IsGenerated(this SyntaxNodeAnalysisContext context, CancellationToken cancellationToken)
internal static bool IsGenerated(this SyntaxNodeAnalysisContext context)
{
return (context.Node.SyntaxTree?.IsGeneratedDocument(cancellationToken) ?? false) || (context.Node?.HasGeneratedAttribute() ?? false);
return IsGeneratedDocument(context.Node.SyntaxTree, context.CancellationToken);
}

/// <summary>
/// Checks whether the given document is auto generated by a tool.
/// </summary>
internal static bool IsGeneratedDocument(this SyntaxTreeAnalysisContext context, CancellationToken cancellationToken)
internal static bool IsGeneratedDocument(this SyntaxTreeAnalysisContext context)
{
return context.Tree?.IsGeneratedDocument(cancellationToken) ?? false;
}

/// <summary>
/// Checks whether the given symbol is auto generated by a tool.
/// </summary>
internal static bool IsGeneratedSymbol(this SymbolAnalysisContext context, CancellationToken cancellationToken)
{
if (context.Symbol == null) return false;
foreach (var syntaxReference in context.Symbol.DeclaringSyntaxReferences)
{
if (syntaxReference.SyntaxTree.IsGeneratedDocument(cancellationToken)) return true;
var root = syntaxReference.SyntaxTree.GetRoot(cancellationToken);
var node = root?.FindNode(syntaxReference.Span);
if (node.HasGeneratedAttribute()) return true;
}
return false;
}

/// <summary>
/// Checks whether the given node has any of several attributes indicating it was generated by a tool.
/// </summary>
internal static bool HasGeneratedAttribute(this SyntaxNode node)
{
return node.HasAttributeOnAncestorOrSelf("GeneratedCode");
return IsGeneratedDocument(context.Tree, context.CancellationToken);
}

/// <summary>
/// Checks whether the given document is auto generated by a tool
/// (based on filename or comment header).
/// </summary>
internal static bool IsGeneratedDocument(this SyntaxTree tree, CancellationToken cancellationToken)
public static bool IsGeneratedDocument(this SyntaxTree tree, CancellationToken cancellationToken)
{
return (tree.FilePath?.IsGeneratedFileName() ?? false) || tree.HasAutoGeneratedComment(cancellationToken);
}
if (tree == null)
{
return false;
}

/// <summary>
/// Checks whether the given document has an auto-generated comment as its header.
/// </summary>
internal static bool HasAutoGeneratedComment(this SyntaxTree tree, CancellationToken cancellationToken)
{
StrongBox<bool?> cachedResult = GeneratedHeaderPresentCheck.GetOrCreateValue(tree);
if (cachedResult.Value.HasValue)
{
return cachedResult.Value.Value;
}

bool autoGenerated = HasAutoGeneratedCommentNoCache(tree, cancellationToken);
bool autoGenerated = IsGeneratedDocumentNoCache(tree, cancellationToken);

// Update the strongbox's value with our computed result.
// This doesn't change the strongbox reference, and its presence in the
Expand All @@ -99,10 +72,15 @@ internal static bool HasAutoGeneratedComment(this SyntaxTree tree, CancellationT
return autoGenerated;
}

private static bool IsGeneratedDocumentNoCache(SyntaxTree tree, CancellationToken cancellationToken)
{
return IsGeneratedFileName(tree.FilePath) || HasAutoGeneratedComment(tree, cancellationToken);
}

/// <summary>
/// Checks whether the given document has an auto-generated comment as its header.
/// </summary>
private static bool HasAutoGeneratedCommentNoCache(SyntaxTree tree, CancellationToken cancellationToken)
private static bool HasAutoGeneratedComment(SyntaxTree tree, CancellationToken cancellationToken)
{
var root = tree.GetRoot(cancellationToken);

Expand All @@ -128,7 +106,7 @@ private static bool HasAutoGeneratedCommentNoCache(SyntaxTree tree, Cancellation
/// <summary>
/// Checks whether the given document has a filename that indicates it is a generated file.
/// </summary>
private static bool IsGeneratedFileName(this string filePath)
private static bool IsGeneratedFileName(string filePath)
{
return Regex.IsMatch(
Path.GetFileName(filePath),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,20 @@ private void AnalyzeField(SymbolAnalysisContext symbolAnalysisContext)
this.IsParentAClass(fieldDeclarationSyntax) &&
!fieldDeclarationSyntax.IsConst)
{
foreach (var location in symbolAnalysisContext.Symbol.Locations)
{
if (!location.IsInSource)
{
// assume symbols not defined in a source document are "out of reach"
return;
}

if (location.SourceTree.IsGeneratedDocument(symbolAnalysisContext.CancellationToken))
{
return;
}
}

symbolAnalysisContext.ReportDiagnostic(Diagnostic.Create(Descriptor, fieldDeclarationSyntax.Locations[0]));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ private void HandleFieldDeclaration(SymbolAnalysisContext context)
char.IsLower(symbol.Name[0]) &&
symbol.Locations.Any())
{
foreach (var location in context.Symbol.Locations)
{
if (!location.IsInSource)
{
// assume symbols not defined in a source document are "out of reach"
return;
}

if (location.SourceTree.IsGeneratedDocument(context.CancellationToken))
{
return;
}
}

context.ReportDiagnostic(Diagnostic.Create(Descriptor, symbol.Locations[0]));
}
}
Expand Down

0 comments on commit d10db47

Please sign in to comment.