Skip to content

Commit

Permalink
optimize FeatureDefinitionAnalyzer (#938)
Browse files Browse the repository at this point in the history
  • Loading branch information
omsmith authored Nov 21, 2023
1 parent 49cc34f commit 6ff5f96
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System.Collections.Immutable;
using D2L.CodeStyle.Analyzers.Extensions;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

namespace D2L.CodeStyle.Analyzers.ApiUsage.LaunchDarkly {
Expand All @@ -11,13 +9,6 @@ internal sealed class FeatureDefinitionAnalyzer : DiagnosticAnalyzer {

public const string FeatureDefinitionFullName = "D2L.LP.LaunchDarkly.FeatureDefinition`1";

private static readonly ImmutableHashSet<string> ValidTypes = ImmutableHashSet.Create<string>(
"int",
"bool",
"string",
"float"
);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
Diagnostics.InvalidLaunchDarklyFeatureDefinition
);
Expand All @@ -38,49 +29,54 @@ private void RegisterAnalysis( CompilationStartAnalysisContext context ) {
return;
}

context.RegisterSyntaxNodeAction(
c => AnalyzeSimpleBaseType( c, featureDefinitionType ),
SyntaxKind.SimpleBaseType
);
context.RegisterSymbolAction(
c => AnalyzeMaybeSubtype( c, featureDefinitionType ),
SymbolKind.NamedType
);
}

private static void AnalyzeSimpleBaseType(
SyntaxNodeAnalysisContext context,
private static void AnalyzeMaybeSubtype(
SymbolAnalysisContext context,
INamedTypeSymbol featureDefinitionType
) {

SimpleBaseTypeSyntax baseTypeSyntax = (SimpleBaseTypeSyntax)context.Node;
SymbolInfo baseTypeSymbol = context.SemanticModel.GetSymbolInfo( baseTypeSyntax.Type, context.CancellationToken );
INamedTypeSymbol maybeSubtype = (INamedTypeSymbol)context.Symbol;

INamedTypeSymbol? baseSymbol = ( baseTypeSymbol.Symbol as INamedTypeSymbol );
if( baseSymbol.IsNullOrErrorType() ) {
if( maybeSubtype.BaseType is null ) {
return;
}

ISymbol originalSymbol = baseSymbol.OriginalDefinition;
if( originalSymbol.IsNullOrErrorType() ) {
if( !SymbolEqualityComparer.Default.Equals( maybeSubtype.BaseType.OriginalDefinition, featureDefinitionType ) ) {
return;
}

if( !originalSymbol.Equals( featureDefinitionType, SymbolEqualityComparer.Default ) ) {
return;
}
ISymbol valueTypeSymbol = maybeSubtype.BaseType.TypeArguments[ 0 ];

ISymbol valueTypeSymbol = baseSymbol.TypeArguments[ 0 ];
if( valueTypeSymbol.IsNullOrErrorType() ) {
return;
}

string valueType = valueTypeSymbol.ToDisplayString();
if( ValidTypes.Contains( valueType ) ) {
if( valueTypeSymbol is INamedTypeSymbol namedValueType
&& IsValidType( namedValueType )
) {
return;
}

var (typeSyntax, baseTypeSyntax) = maybeSubtype.ExpensiveGetSyntaxImplementingType( maybeSubtype.BaseType, context.Compilation, context.CancellationToken );

context.ReportDiagnostic(
Diagnostics.InvalidLaunchDarklyFeatureDefinition,
baseTypeSyntax.GetLocation(),
messageArgs: new[] { valueType }
location: baseTypeSyntax?.GetLocation() ?? typeSyntax?.Identifier.GetLocation() ?? Location.None,
messageArgs: new[] { valueTypeSymbol.ToDisplayString() }
);
}

private static bool IsValidType( INamedTypeSymbol valueType ) => valueType.SpecialType switch {
SpecialType.System_Int32 => true,
SpecialType.System_Boolean => true,
SpecialType.System_String => true,
SpecialType.System_Single => true,
_ => false
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,30 @@ namespace SpecTests {
using System;
using D2L.LP.LaunchDarkly;

public sealed class ObjectDefinition :/* InvalidLaunchDarklyFeatureDefinition(long) */ FeatureDefinition<long> /**/{ }
public sealed class LongDefinition :/* InvalidLaunchDarklyFeatureDefinition(long) */ FeatureDefinition<long> /**/{ }
public sealed class ObjectDefinition :/* InvalidLaunchDarklyFeatureDefinition(System.TimeSpan) */ FeatureDefinition<TimeSpan> /**/{ }

public sealed class BoolDefinition : FeatureDefinition<bool> { }
public sealed class FloatDefinition : FeatureDefinition<float> { }
public sealed class IntDefinition : FeatureDefinition<int> { }
public sealed class StringDefinition : FeatureDefinition<string> { }

public sealed class BoolDefinition : FeatureDefinition<Boolean> { }
public sealed class FloatDefinition : FeatureDefinition<Single> { }
public sealed class IntDefinition : FeatureDefinition<Int32> { }
public sealed class StringDefinition : FeatureDefinition<String> { }

public sealed class BoolDefinition : FeatureDefinition<System.Boolean> { }
public sealed class FloatDefinition : FeatureDefinition<System.Single> { }
public sealed class IntDefinition : FeatureDefinition<System.Int32> { }
public sealed class StringDefinition : FeatureDefinition<System.String> { }
public sealed class GenericDefinition<T> : /* InvalidLaunchDarklyFeatureDefinition(T) */ FeatureDefinition<T> /**/ { }

namespace Keywords {
public sealed class BoolDefinition : FeatureDefinition<bool> { }
public sealed class FloatDefinition : FeatureDefinition<float> { }
public sealed class IntDefinition : FeatureDefinition<int> { }
public sealed class StringDefinition : FeatureDefinition<string> { }
}

namespace SystemType {
public sealed class BoolDefinition : FeatureDefinition<Boolean> { }
public sealed class FloatDefinition : FeatureDefinition<Single> { }
public sealed class IntDefinition : FeatureDefinition<Int32> { }
public sealed class StringDefinition : FeatureDefinition<String> { }
}

namespace QualifiedSystemType {
public sealed class BoolDefinition : FeatureDefinition<System.Boolean> { }
public sealed class FloatDefinition : FeatureDefinition<System.Single> { }
public sealed class IntDefinition : FeatureDefinition<System.Int32> { }
public sealed class StringDefinition : FeatureDefinition<System.String> { }
}
}

namespace MissingLaunchDarklyUsingStatement {
Expand All @@ -36,4 +43,4 @@ namespace UnresolvedValueType {
using D2L.LP.LaunchDarkly;

public sealed class ObjectDefinition : FeatureDefinition<YMCA> { }
}
}

0 comments on commit 6ff5f96

Please sign in to comment.