Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,13 @@ public static (INamedTypeSymbol? enumExtensionsAttr, ExternalEnumDictionary? ext
var externalEnumTypes = new ExternalEnumDictionary(SymbolEqualityComparer.Default);
if (externalEnumExtensionsAttr is not null)
{
foreach (var attribute in compilation.Assembly.GetAttributes())
// Check current assembly
ScanAssemblyAttributes(compilation.Assembly, externalEnumExtensionsAttr, externalEnumTypes);

// Check referenced assemblies
foreach (var referencedAssembly in compilation.SourceModule.ReferencedAssemblySymbols)
{
if (attribute.AttributeClass is { IsGenericType: true } attrClass &&
SymbolEqualityComparer.Default.Equals(attrClass.ConstructedFrom, externalEnumExtensionsAttr) &&
attrClass.TypeArguments is [INamedTypeSymbol { TypeKind: TypeKind.Enum } enumType])
{
var details = ExtractExtensionClassDetails(enumType, attribute);
externalEnumTypes.Add(enumType, details);
}
ScanAssemblyAttributes(referencedAssembly, externalEnumExtensionsAttr, externalEnumTypes);
}
}

Expand Down Expand Up @@ -67,6 +65,23 @@ public static bool IsEnumWithExtensions(
return false;
}

private static void ScanAssemblyAttributes(
IAssemblySymbol assembly,
INamedTypeSymbol externalEnumExtensionsAttr,
ExternalEnumDictionary externalEnumTypes)
{
foreach (var attribute in assembly.GetAttributes())
{
if (attribute.AttributeClass is { IsGenericType: true } attrClass &&
SymbolEqualityComparer.Default.Equals(attrClass.ConstructedFrom, externalEnumExtensionsAttr) &&
attrClass.TypeArguments is [INamedTypeSymbol { TypeKind: TypeKind.Enum } enumType])
{
var details = ExtractExtensionClassDetails(enumType, attribute);
externalEnumTypes[enumType] = details;
}
}
}

private static string ExtractExtensionClassDetails(
ITypeSymbol receiverType,
AttributeData attributeData)
Expand Down
67 changes: 67 additions & 0 deletions tests/NetEscapades.EnumGenerators.Tests/IsDefinedAnalyzerTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using System;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Testing;
using Microsoft.CodeAnalysis.Testing;
using NetEscapades.EnumGenerators.Diagnostics.UsageAnalyzers;
using Xunit;

Expand Down Expand Up @@ -571,6 +574,70 @@ public void TestMethod()
await VerifyAnalyzerAsync(test, EnableState.Disabled);
}

[Fact]
public async Task IsDefinedOnEnumFromReferencedAssemblyWithAssemblyLevelEnumExtensionsShouldHaveDiagnostic()
{
var mainCode = """
using System;
using ExternalNamespace;

namespace ConsoleApplication1
{
public class TestClass
{
public void TestMethod()
{
var value = ExternalEnum.Value1;
var isDefined = {|NEEG006:Enum.IsDefined(typeof(ExternalEnum), value)|};
}
}
}

namespace ExternalNamespace
{
// This code would be generated, just hacked in here for simplicity
public static class ExternalEnumExtensions
{
public static bool IsDefined(ExternalEnum value) => true;
}
}
""";

var externalCode = $$"""
[assembly: NetEscapades.EnumGenerators.EnumExtensions<ExternalNamespace.ExternalEnum>()]

namespace ExternalNamespace
{
public enum ExternalEnum
{
Value1 = 1,
Value2 = 2,
}
}

{{TestHelpers.LoadEmbeddedAttribute()}}
{{TestHelpers.LoadEmbeddedMetadataSource()}}
""";

var test = new CSharpAnalyzerTest<IsDefinedAnalyzer, DefaultVerifier>
{
TestCode = mainCode,
};

test.TestState.AdditionalProjects.Add("ExternalProject", new ProjectState("ExternalProject", LanguageNames.CSharp, "external_", ".cs"));
test.TestState.AdditionalProjects["ExternalProject"].Sources.Add(("external_Code.cs", externalCode));
test.TestState.AdditionalProjectReferences.Add("ExternalProject");

test.TestState.AnalyzerConfigFiles.Add(
("/.editorconfig",
$"""
is_global = true
{UsageAnalyzerConfig.EnableKey} = true
"""));

await test.RunAsync();
}

private static string GetTestCodeWithExternalEnum(string testCode) => $$"""
using System;
using System.Collections.Generic;
Expand Down
Loading