Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Roslyn analyzer: "does not have accessible to set from the same dll. It cannot support to inject by the source generator." #730

Open
RedGlow opened this issue Dec 11, 2024 · 1 comment

Comments

@RedGlow
Copy link

RedGlow commented Dec 11, 2024

Hello,
I'm trying to use the Roslyn source generator approach on a Unity 6 project.

I've started from a minimal project that contains the following definitions:

Service.cs

namespace Test
{
    public class Service
    {
        public string Hello()
        {
            return "Hello";
        }
    }
}

View.cs

using UnityEngine;
using VContainer;

namespace Test
{
    public class View: MonoBehaviour
    {
        [Inject] public Service Service { get; set; }

        private void Start()
        {
            Debug.Log(Service.Hello());
        }
    }
}

GameLifetimeScope.cs

using Test;
using VContainer;
using VContainer.Unity;

public class GameLifetimeScope : LifetimeScope
{
    protected override void Configure(IContainerBuilder builder)
    {
        builder.Register<Service>(Lifetime.Scoped);
    }
}

And a simple hierarchy:
image
image

With this setup, the view correctly prints the message.

From my understanding, I could remove the auto-inject of the View game object and use source generation. I followed the instructions above, but then I get this compilation error:

Assets\Test\View.cs(8,33): warning VCON0008: The [Inject] 'Service' does not have accessible to set from the same dll. It cannot support to inject by the source generator.

It's not really clear to me what this phrase means. Looking for this error in the source code I found this snippet:

if (propSymbol.SetMethod == null || !propSymbol.SetMethod.IsInitOnly || !propSymbol.SetMethod.CanBeCallFromInternal())
{
    context.ReportDiagnostic(Diagnostic.Create(
        DiagnosticDescriptors.PrivatePropertyNotSupported,
        propSymbol.Locations.FirstOrDefault() ?? typeMeta.GetLocation(),
        propSymbol.Name));
    error = true;
}

Which seems to indicate that the following conditions must be met:

  • the property must have a setter
  • the setter must not be an init (maybe?)
  • and must have at least an "internal" level

That "init" part made me curious, so I changed the definition of the property from {get; set;} to {get; init;}, by adding the IsExternalInit which is missing according to Unity documentation, and at that point the source generator actually produced the code (even though the code seems to indicate the contrary), but then it obviously failed the compilation with the error VContainer.SourceGenerator\VContainer.SourceGenerator.VContainerIncrementalSourceGenerator\Test.ViewGeneratedInjector.g.cs(19,14): error CS8852: Init-only property or indexer 'View.Service' can only be assigned in an object initializer, or on 'this' or 'base' in an instance constructor or an 'init' accessor. because it needs a setter:

__x.Service = (global::Test.Service)resolver.ResolveOrParameter(typeof(global::Test.Service), "Service", parameters);

My suspect is that the IsInitOnly property is wrong in Unity 6, but I didn't dig any further in the code.

You can find my test project here: https://github.com/RedGlow/vcontainer-bug-report .

@hadashiA
Copy link
Owner

Thank you for your detailed report.

After checking, it seems that there was my mistake in the conditional expression in the source code you provided.

I've confirmed that the problem has been solved with the fix for #738, so I've merged it.
We'll release it soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants