AArnott / CodeGeneration.Roslyn

Assists in performing Roslyn-based code generation during a build.
Microsoft Public License
408 stars 59 forks source link

My generator class cannot find one of its dependencys #61

Closed LokiMidgard closed 6 years ago

LokiMidgard commented 6 years ago

I updated my Project from version 0.3.9 of this library to current 0.4.11. The Sample DuplicateWithSuffix is working, but my generator stopped working.

It does not produce any kind of error output. After some debugging I think the problem is that the Type of my Generator cannot be loaded because a dependency is missing.

When I create an instance of my Generator in the constructor of DuplicateWithSuffixGenerator the build process prints an exception stack trace. Which claims the assembly NDProperty.Core can't be found. This is another project my Generator depends on.

1>Target GenerateCodeFromAttributes:
1>  Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException: Could not load file or assembly 'NDProperty.Core, Version=0.14.0.0, Culture=neutral, PublicKeyToken=null'. Das System kann die angegebene Datei nicht finden.
1>     at NDProperty.Generator.DuplicateWithSuffixGenerator..ctor(AttributeData attributeData)
1>     --- End of inner exception stack trace ---
1>     at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
1>     at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
1>     at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
1>     at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
1>     at System.Activator.CreateInstance(Type type, Object[] args)
1>     at CodeGeneration.Roslyn.DocumentTransform.<FindCodeGenerators>d__2.MoveNext()
1>     at CodeGeneration.Roslyn.DocumentTransform.<TransformAsync>d__1.MoveNext()
1>  --- End of stack trace from previous location where exception was thrown ---
1>     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
1>     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
1>     at CodeGeneration.Roslyn.CompilationGenerator.Generate(IProgress`1 progress, CancellationToken cancellationToken)
1>     at CodeGeneration.Roslyn.Generate.Program.Main(String[] args)

My DuplicateWith SuffixGenerator code:

   public class DuplicateWithSuffixGenerator : ICodeGenerator
    {
        private readonly string suffix;

        public DuplicateWithSuffixGenerator(AttributeData attributeData)
        {
            //System.Diagnostics.Debugger.Launch();
            var y = new Generator.NDPGeneratorProperty(attributeData); // <-- Removing this it will work again.
            Requires.NotNull(attributeData, nameof(attributeData));

            var d = attributeData.NamedArguments.ToDictionary(x => x.Key, x => x.Value);

            if (d.ContainsKey(nameof(DuplicateWithSuffixAttribute.Suffix)))
                this.suffix = d[nameof(DuplicateWithSuffixAttribute.Suffix)].Value.ToString() +"_EWE";
            else
                this.suffix = (d.FirstOrDefault().Key ?? "NOKEY")+ "_mes";
            //this.suffix = (string)attributeData.ConstructorArguments[0].Value;
        }

        public Task<SyntaxList<MemberDeclarationSyntax>> GenerateAsync(TransformationContext context, IProgress<Diagnostic> progress, CancellationToken cancellationToken)
        {
            var results = SyntaxFactory.List<MemberDeclarationSyntax>();

            // Our generator is applied to any class that our attribute is applied to.
            var applyToClass = (ClassDeclarationSyntax)context.ProcessingMember;

            // Apply a suffix to the name of a copy of the class.
            var copy = applyToClass
                .WithIdentifier(SyntaxFactory.Identifier(applyToClass.Identifier.ValueText + this.suffix));

            // Return our modified copy. It will be added to the user's project for compilation.
            results = results.Add(copy);
            return Task.FromResult<SyntaxList<MemberDeclarationSyntax>>(results);
        }
    }

    [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
    [CodeGenerationAttribute(typeof(DuplicateWithSuffixGenerator))]
    //[CodeGenerationAttribute(typeof(Generator.NDPGeneratorProperty))]
    [System.Diagnostics.Conditional("CodeGeneration")]
    public class DuplicateWithSuffixAttribute : Attribute
    {
        //public DuplicateWithSuffixAttribute(string suffix)
        //{
        //    Requires.NotNullOrEmpty(suffix, nameof(suffix));

        //    this.Suffix = suffix;
        //}
        public DuplicateWithSuffixAttribute()
        {

        }
        public string Suffix { get; set; }
        public Propertys.NDPropertySettings Settings { get; set; } = Propertys.NDPropertySettings.None;
    }

Is a dependency on another project no longer supported? I pretty heavily using typeof and nameof. Or should it work and the error is somewhere else?

Nither ProjectReference nor PackageReference will work. The nuget package contains the missing DLL.

LokiMidgard commented 6 years ago

I've found an article that seems to describe the Problem. It seems you can find the assembly's referenced by the target assembly using a .deps.json file generated at build. I will try to test this.

AArnott commented 6 years ago

I'm closing this, supposing that #62 addressed the need.