kekekeks / XamlX

General purpose pluggable XAML compiler with no runtime dependencies.
MIT License
321 stars 55 forks source link

XamlParserTests crashes with dotnet test exception for net47 #34

Open rstm-sf opened 4 years ago

rstm-sf commented 4 years ago

Hello!

XamlParserTests crashes with dotnet test exception for net47

dotnet test -f net47 --filter Compiler_Should_Compile_Simple_Xaml .\tests\XamlParserTests\XamlParserTests.csproj
``` Test run for D:\a\XamlX\XamlX\tests\XamlParserTests\bin\Debug\net47\XamlParserTests.dll(.NETFramework,Version=v4.7) Microsoft (R) Test Execution Command Line Tool Version 16.7.0 Copyright (c) Microsoft Corporation. All rights reserved. Starting test execution, please wait... A total of 1 test files matched the specified pattern. [xUnit.net 00:00:00.19] xUnit.net VSTest Adapter v2.4.3+1b45f5407b (32-bit Desktop .NET 4.0.30319.42000) [xUnit.net 00:00:03.15] Discovering: XamlParserTests [xUnit.net 00:00:03.42] Discovered: XamlParserTests [xUnit.net 00:00:03.43] Starting: XamlParserTests √ XamlParserTests.BasicCompilerTests.Compiler_Should_Compile_Simple_Xaml(populate: False) [1s 141ms] [xUnit.net 00:00:05.66] XamlParserTests.BasicCompilerTests.Compiler_Should_Compile_Simple_Xaml(populate: True) [FAIL] [xUnit.net 00:00:05.66] System.InvalidOperationException : Collection was modified; enumeration operation may not execute. [xUnit.net 00:00:05.66] Stack Trace: [xUnit.net 00:00:05.67] at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) [xUnit.net 00:00:05.67] at System.Collections.Generic.List`1.Enumerator.MoveNextRare() [xUnit.net 00:00:05.67] at System.Collections.Generic.List`1.Enumerator.MoveNext() [xUnit.net 00:00:05.67] D:\a\XamlX\XamlX\src\XamlX\Transform\XamlXmlnsMappings.cs(22,0): at XamlX.Transform.XamlXmlnsMappings.Resolve(IXamlTypeSystem typeSystem, XamlLanguageTypeMappings typeMappings) [xUnit.net 00:00:05.67] D:\a\XamlX\XamlX\src\XamlX\Transform\TransformerConfiguration.cs(59,0): at XamlX.Transform.TransformerConfiguration..ctor(IXamlTypeSystem typeSystem, IXamlAssembly defaultAssembly, XamlLanguageTypeMappings typeMappings, XamlXmlnsMappings xmlnsMappings, XamlValueConverter customValueConverter) [xUnit.net 00:00:05.67] CompilerTestBase.cs(30,0): at XamlParserTests.CompilerTestBase..ctor(IXamlTypeSystem typeSystem) [xUnit.net 00:00:05.67] CompilerTestBase.cs(82,0): at XamlParserTests.CompilerTestBase..ctor() [xUnit.net 00:00:05.67] at XamlParserTests.BasicCompilerTests..ctor() [xUnit.net 00:00:05.67] at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) [xUnit.net 00:00:05.67] Finished: XamlParserTests X XamlParserTests.BasicCompilerTests.Compiler_Should_Compile_Simple_Xaml(populate: True) [1ms] Error Message: System.InvalidOperationException : Collection was modified; enumeration operation may not execute. Stack Trace: at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) at System.Collections.Generic.List`1.Enumerator.MoveNextRare() at System.Collections.Generic.List`1.Enumerator.MoveNext() at XamlX.Transform.XamlXmlnsMappings.Resolve(IXamlTypeSystem typeSystem, XamlLanguageTypeMappings typeMappings) in D:\a\XamlX\XamlX\src\XamlX\Transform\XamlXmlnsMappings.cs:line 22 at XamlX.Transform.TransformerConfiguration..ctor(IXamlTypeSystem typeSystem, IXamlAssembly defaultAssembly, XamlLanguageTypeMappings typeMappings, XamlXmlnsMappings xmlnsMappings, XamlValueConverter customValueConverter) in D:\a\XamlX\XamlX\src\XamlX\Transform\TransformerConfiguration.cs:line 59 at XamlParserTests.CompilerTestBase..ctor(IXamlTypeSystem typeSystem) in D:\a\XamlX\XamlX\tests\XamlParserTests\CompilerTestBase.cs:line 30 Test Run Failed. at XamlParserTests.CompilerTestBase..ctor() in D:\a\XamlX\XamlX\tests\XamlParserTests\CompilerTestBase.cs:line 82 at XamlParserTests.BasicCompilerTests..ctor() at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) Total tests: 2 Passed: 1 Failed: 1 Total time: 11.4751 Seconds ```

If you write ToList() here, then everything will be fine https://github.com/kekekeks/XamlX/blob/697a419675a8055b7ef9a1904360359522b30616/src/XamlX/IL/SreTypeSystem.cs#L18

Unlike #33, here it seems to me that the problem of the main library

kekekeks commented 4 years ago

Since collection is guaranteed to be append-only, we should probably use a specialized enumerator there, e. g.


    struct AppendOnlyListEnumerator<T> : IEnumerator<T>
    {
        private readonly IReadOnlyList<T> _list;
        private int _index;

        public AppendOnlyListEnumerator(IReadOnlyList<T> list)
        {
            _list = list;
            _index = -1;
        }

        public bool MoveNext()
        {
            if (_list.Count > _index + 1)
            {
                _index++;
                return true;
            }
            return false;
        }

        public void Reset() => _index = -1;

        public T Current => _list[_index];

        object IEnumerator.Current => Current;

        public void Dispose()
        {
        }
    }

    struct AppendOnlyEnumerable<T> : IEnumerable<T>
    {
        private readonly IReadOnlyList<T> _list;

        public AppendOnlyEnumerable(IReadOnlyList<T> list)
        {
            _list = list;
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new AppendOnlyListEnumerator<T>(_list);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

    static class ListExtensions
    {
        public static AppendOnlyEnumerable<T> EnumerateAsAppendOnly<T>(this List<T> list) =>
            new AppendOnlyEnumerable<T>(list);
    }
rstm-sf commented 4 years ago

Can we replace IReadOnlyList with IEnumerable in a similar way?