icsharpcode / NRefactory

NRefactory - Refactoring Your C# Code
684 stars 264 forks source link

Does NRefactory understand WinRT language projections? #399

Open ghost opened 10 years ago

ghost commented 10 years ago

Does NRefactory understand WinRT language projection from C#? If not then what would be the easiest way to add this functionality to NRefactory?

The following unit test seems to indicate that it does not currently support it. Resolving Windows.Globalization.ApplicationLanguages.Languages[0] should resolve to System.String, but this fails. My theory is that the resolver expects to find an indexer, but there isn't one because it is actually a project of IVector.GetAt(...).

To reproduce this issue, clone NRefactory, and add the file ICSharpCode.NRefactory.Tests\CSharp\Resolver\WinrtTests.cs:

using ICSharpCode.NRefactory.TypeSystem;
using NUnit.Framework;

namespace ICSharpCode.NRefactory.CSharp.Resolver
{
    public class WinrtTests : ResolverTestBase
    {
        public override void SetUp()
        {
            var loader = new CecilLoader();
            project = new CSharpProjectContent().AddAssemblyReferences(new [] {
                CecilLoaderTests.Mscorlib,
                loader.LoadAssemblyFile(@"C:\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Windows.winmd")
            });
            compilation = project.CreateCompilation();
        }

        [Test]
        public void FixedStatement()
        {
            const string program =
                @"class TestClass
                {
                    static void Main()
                    {
                        var i = $Windows.Globalization.ApplicationLanguages.Languages[0]$;
                    }
                }";

            var rr = Resolve(program);
            Assert.AreEqual("System.String", rr.Type.FullName);
        }
    }
}
dgrunwald commented 10 years ago

No, NRefactory currently does not understand the language projections.

Is there some documentation on the projections supported by C#? We might be able to apply these as the WinRT metadata gets imported into the NR type system.

dgrunwald commented 10 years ago

I'm not exactly sure on how the language projections work... do they add methods to the IVector interface, or do they replace the return type of the ApplicationLanguages.Languages property with IList? But either way, I think the easiest solution is to perform this modification in the NR AssemblyLoader.

ghost commented 10 years ago

As far as documentation on the matter goes, the following should just about cover it. http://msdn.microsoft.com/en-us/library/windows/apps/hh995050.aspx http://go.microsoft.com/fwlink/p/?LinkId=243099

dgrunwald commented 10 years ago

OK, so this indeed seems to be a case of replacing the return types/parameter types etc.

I think that the implementation should be easy: In the AssemblyLoader (both Cecil and IKVM implementations), when creating one of the mapped types, don't actually create the WinRT type, but instead add a type forwarder to the corresponding CLR type.

The static readonly Dictionary<TopLevelTypeName, ITypeReference> mappedWindowsRuntimeTypes can be placed in the AssemblyLoader base class so that it can be used by both the Cecil and IKVM implementations.

dgrunwald commented 10 years ago

Actually, do we need this for both Cecil and IKVM? Current IKVM versions seem to have WinMD projection support already built in.