Пример #1
0
        public OnReadyGetAddition(MemberAttributeSite memberSite)
            : base(memberSite.AttributeSite.Class)
        {
            Member = memberSite.Member;

            // Handle field name convention: _ prefix with lowercase name.
            string pathName = Member.Name.TrimStart('_');

            pathName =
                pathName[0].ToString().ToUpperInvariant() +
                pathName.Substring(1);

            SuffixlessExportPropertyName = pathName;

            foreach (var constructorArg in memberSite.AttributeSite.Attribute.ConstructorArguments)
            {
                if (constructorArg.Value is string path)
                {
                    Path = path;
                }
            }

            foreach (var namedArg in memberSite.AttributeSite.Attribute.NamedArguments)
            {
                switch (namedArg.Key)
                {
                case "Path" when namedArg.Value.Value is string s:
                    Path = s;
                    break;

                case "Export" when namedArg.Value.Value is bool b:
                    Export = b;
                    break;

                case "OrNull" when namedArg.Value.Value is bool b:
                    OrNull = b;
                    break;

                case "Property" when namedArg.Value.Value is string s:
                    Property = s;
                    break;

                case "NonRecursive" when namedArg.Value.Value is bool b:
                    NonRecursive = b;
                    break;

                case "Unowned" when namedArg.Value.Value is bool b:
                    Unowned = b;
                    break;
                }
            }
        }
Пример #2
0
 public OnReadyGetNodeAddition(MemberAttributeSite site) : base(site)
 {
 }
Пример #3
0
        public void Execute(GeneratorExecutionContext context)
        {
            // If this isn't working, run 'dotnet build-server shutdown' first.
            if (Environment
                .GetEnvironmentVariable($"Debug{nameof(GodotOnReadySourceGenerator)}") == "true")
            {
                Debugger.Launch();
            }

            var receiver = context.SyntaxReceiver as OnReadyReceiver ?? throw new Exception();

            INamedTypeSymbol GetSymbolByName(string fullName) =>
            context.Compilation.GetTypeByMetadataName(fullName)
            ?? throw new Exception($"Can't find {fullName}");

            var onReadyGetSymbol = GetSymbolByName("GodotOnReady.Attributes.OnReadyGetAttribute");
            var onReadySymbol    = GetSymbolByName("GodotOnReady.Attributes.OnReadyAttribute");
            var generateDataSelectorEnumSymbol =
                GetSymbolByName("GodotOnReady.Attributes.GenerateDataSelectorEnumAttribute");

            var resourceSymbol = GetSymbolByName("Godot.Resource");
            var nodeSymbol     = GetSymbolByName("Godot.Node");

            List <PartialClassAddition> additions = new();

            var classSymbols = receiver.AllClasses
                               .Select(classDecl =>
            {
                INamedTypeSymbol?classSymbol = context.Compilation
                                               .GetSemanticModel(classDecl.SyntaxTree)
                                               .GetDeclaredSymbol(classDecl);

                if (classSymbol is null)
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            new DiagnosticDescriptor(
                                "GORSG0001",
                                "Inspection",
                                $"Unable to find declared symbol for {classDecl}. Skipping.",
                                "GORSG.Parsing",
                                DiagnosticSeverity.Warning,
                                true
                                ),
                            classDecl.GetLocation()
                            )
                        );
                }

                return(classSymbol);
            })
                               .Distinct(SymbolEqualityComparer.Default)
                               .OfType <INamedTypeSymbol>();

            foreach (var classSymbol in classSymbols)
            {
                foreach (var attribute in classSymbol.GetAttributes()
                         .Where(a => Equal(a.AttributeClass, generateDataSelectorEnumSymbol)))
                {
                    var fields = classSymbol.GetMembers()
                                 .OfType <IFieldSymbol>()
                                 .Where(f => f.IsReadOnly && f.IsStatic)
                                 .ToArray();

                    additions.Add(new DataSelectorEnumAddition(
                                      fields,
                                      new AttributeSite(classSymbol, attribute)));
                }

                var members = Enumerable
                              .Concat(
                    classSymbol.GetMembers().OfType <IPropertySymbol>().Select(MemberSymbol.Create),
                    classSymbol.GetMembers().OfType <IFieldSymbol>().Select(MemberSymbol.Create))
                              .ToArray();

                foreach (var member in members)
                {
                    foreach (var attribute in member.Symbol
                             .GetAttributes()
                             .Where(a => Equal(a.AttributeClass, onReadyGetSymbol)))
                    {
                        var site = new MemberAttributeSite(
                            member,
                            new AttributeSite(classSymbol, attribute));

                        if (site.AttributeSite.Attribute.NamedArguments.Any(
                                a => a.Key == "Property" && a.Value.Value is string { Length: > 0 }))
Пример #4
0
 public OnReadyGetResourceAddition(MemberAttributeSite site) : base(site)
 {
 }
        public InjectAncestorValueAddition(MemberAttributeSite memberSite)
            : base(memberSite.AttributeSite.Class)
        {
            Member = memberSite.Member;

            _nodeType = (INamedTypeSymbol)Member.Type;
            _nodeName = _nodeType.Name;

            var args = memberSite.AttributeSite.Attribute.ConstructorArguments;

            if (args.Length > 0)
            {
                if (args[0].Value is INamedTypeSymbol s)
                {
                    _nodeType = s;
                    _nodeName = _nodeType.Name;
                }
            }
            if (args.Length > 1)
            {
                if (args[1].Value is string s)
                {
                    _nodeName = s;
                }
            }

            // We don't want the node, we want a property or field of the node with a specific type.
            if (!Member.Type.Equals(_nodeType, SymbolEqualityComparer.Default))
            {
                var matches = MemberSymbol.CreateAll(_nodeType)
                              .Where(s =>
                                     // Ignore backing fields.
                                     !s.Symbol.IsImplicitlyDeclared &&
                                     s.Type.IsOfBaseType(Member.Type))
                              .ToArray();

                if (matches.Length == 0)
                {
                    string issue =
                        $"No field or property of type \"{Member.Type.ToFullDisplayString()}\" " +
                        $"found in injection source \"{_nodeType.ToFullDisplayString()}\". " +
                        "Expected exactly one";

                    Diagnostics.Add(
                        Diagnostic.Create(
                            new DiagnosticDescriptor(
                                "GORSG0004",
                                "Inspection",
                                issue,
                                "GORSG.Parsing",
                                DiagnosticSeverity.Error,
                                true
                                ),
                            Member.Symbol.Locations.FirstOrDefault()
                            )
                        );
                }
                else if (matches.Length > 1)
                {
                    string issue =
                        $"Multiple members of type \"{Member.Type.ToFullDisplayString()}\" " +
                        $"found in injection source {_nodeType.ToFullDisplayString()}, " +
                        "but expected exactly one. Found: " +
                        string.Join(", ", matches.Select(m => m.Name));

                    Diagnostics.Add(
                        Diagnostic.Create(
                            new DiagnosticDescriptor(
                                "GORSG0005",
                                "Inspection",
                                issue,
                                "GORSG.Parsing",
                                DiagnosticSeverity.Error,
                                true
                                ),
                            Member.Symbol.Locations.FirstOrDefault()
                            )
                        );
                }
                else
                {
                    _sourceMember = matches[0];
                }
            }
        }