ILSpy
ILSpy copied to clipboard
AnalyserScope goes to infinite loop when analysing public inner class
Steps to reproduce
Open an assembly where an inner public class exists. Then select Analyse in the context menu. Analysis result would never shown.
Error message shown
No error message shown
Details
- Product in use: ILSpy
- Version in use: commit 84c5e6337014c5439349f2e29eb82b87f1813371
- Any other relevant information to the issue, or your interest in contributing a fix. I have the fix....
Fix:
static void DetermineEffectiveAccessibility(IEntity input, out ITypeDefinition typeScope, out Accessibility accessibility)
{
if (input is ITypeDefinition td)
{
accessibility = Accessibility.Public;
typeScope = td;
}
else
{
accessibility = input.Accessibility;
typeScope = input.DeclaringTypeDefinition;
}
// Once we reach a private entity, we leave the loop with typeScope set to the class that
// contains the private entity = the scope that needs to be searched.
// Otherwise (if we don't find a private entity) we return the top-level class.
var prevTypeScope = typeScope;
while (typeScope != null && !accessibility.LessThanOrEqual(Accessibility.Private))
{
accessibility = accessibility.Intersect(typeScope.Accessibility);
typeScope = typeScope.DeclaringTypeDefinition;
}
if (typeScope == null)
{
typeScope = prevTypeScope;
}
}
Test:
[TestFixture]
public class AnalyzerScopeTests
{
public class TestClass
{
}
[Test]
public void WhenPublicNestedClass_ThenNotInfiniteLoop()
{
// Given
ILSpyX.AssemblyList assemblyList = new ILSpyX.AssemblyList();
var file = new PEFile(this.GetType().Assembly.Location);
var td = file.Metadata.TypeDefinitions.First(td => td.GetFullTypeName(file.Metadata).Name == nameof(TestClass));
Decompiler.Metadata.IAssemblyResolver assemblyResolver = new UniversalAssemblyResolver(null, false, null);
ICompilation compilation = new DecompilerTypeSystem(file, assemblyResolver);
ITypeResolveContext context = new CSharpResolver(compilation);
var module = ((IModuleReference)file).Resolve(context) as MetadataModule;
IEntity entity = module.GetDefinition(td);
// When
var task = Task.Run(() => {
var target = new AnalyzerScope(assemblyList, entity);
});
var result = Task.WaitAny(new[] { task, Task.Delay(500) }); // 0.5 seconds
// Then
Assert.That(result == 0, "The constructor should completes in no longer than 0.5 seconds");
}
}
My push was rejected. I am not sure how to contribute...