daveoftheparty / speedy-moq

Generate boilerplate code for Moq in C#
MIT License
1 stars 0 forks source link

problem with namespaces not being qualified in interface definition save/lookup #36

Closed daveoftheparty closed 3 years ago

daveoftheparty commented 3 years ago

During development I wondered about interface namespaces. Currently storing interface definitions in a dictionary by interface name only...

Whelp, as I guessed, it causes a problem when there are multiple interfaces in unique namespaces with the same name. Need to qualify the namespace in the dictionary, and, it might cause issues for users because if they type in an interface name, which one to look up? Assume same namespace? Assume "closest" neighbor? In the example below, if the user types in IThing, should they get text edits for the bugrepro.IThing, or the bugrepro.Tests.IThing?

uh, oh, spaghetti ohs:

using System;
using System.Linq.Expressions;
using Moq;
using NUnit.Framework;

namespace bugrepro
{
    public interface IThing
    {
        void DoThing();
    }

    public class Tests
    {
        public interface IThing
        {
            void OtherThing();
        }

        [Test]
        public void Test1()
        {
            var thing = new Mock<IThing>();

            Expression<Action<IThing>> doThing = x => x.DoThing();
            thing
                .Setup(doThing)
                .Callback(() =>
                {
                    return;
                });

            Expression<Action<IThing>> otherThing = x => x.OtherThing();
            thing
                .Setup(otherThing)
                .Callback(() =>
                {
                    return;
                });

            thing.Verify(doThing, Times.Once);
            thing.Verify(otherThing, Times.Once);
        }
    }
}
daveoftheparty commented 3 years ago

Got maybe the bulk of this worked out. InterfaceStore used to return a simple InterfaceDefinition.

Now, InterfaceStore returns Dictionary<string, InterfaceDefinition> where the string keys are the different namespaces.

I have MockText and Diagnoser wired up with the changes, along with CodeActionHandler.

It "basically works" but might need some improvement: right now, the code action/lightbulb will let you choose which namespace you require and will output the appropriated moq generation, however, that can lead to the IDE/other code diagnostics complaining that "interface X doesn't contain member Y" because either

Technically, I could leave the proper imports/namespace qualification up to the user... and I might. But if it's not too much extra work, I'll change the MockText service to output the fully qualified name, ie:

var thing = new Mock<bugrepro.Tests.IThing>();
Expression<Action<bugrepro.Tests.IThing>> otherThing = x => x.OtherThing();
thing
    .Setup(otherThing)
    .Callback(() =>
    {
        return;
    });

thing.Verify(otherThing, Times.Once);