Exemplo n.º 1
0
 public PropertyInfo(VariantType type, string name, PropertyHint hint,
                     string?hintString, PropertyUsageFlags usage, bool exported)
 {
     Type       = type;
     Name       = name;
     Hint       = hint;
     HintString = hintString;
     Usage      = usage;
     Exported   = exported;
 }
 private void AppendPropertyConstraint(string sourceVar, PropertyHint propertyHint, string valueVar)
 {
     if (propertyHint.MappingType == PropertyMappingType.InverseArc)
     {
         QueryBuilder.AddTripleConstraint(GraphNode.Variable, valueVar, GraphNode.Iri, propertyHint.SchemaTypeUri,
                                          GraphNode.Variable, sourceVar);
     }
     else
     {
         QueryBuilder.AddTripleConstraint(GraphNode.Variable, sourceVar, GraphNode.Iri, propertyHint.SchemaTypeUri,
                                          GraphNode.Variable, valueVar);
     }
 }
        protected bool HandleAddressOrIdEquals(Expression left, Expression right)
        {
            string       itemName     = null;
            PropertyHint propertyHint = GetPropertyHint(left);

            if (propertyHint == null ||
                !(propertyHint.MappingType == PropertyMappingType.Address ||
                  propertyHint.MappingType == PropertyMappingType.Id))
            {
                return(false);
            }
            if (left is SelectVariableNameExpression)
            {
                itemName = (left as SelectVariableNameExpression).Name;
            }
            else if (left is MemberExpression)
            {
                var m = left as MemberExpression;
                if (m.Expression is QuerySourceReferenceExpression)
                {
                    itemName = (m.Expression as QuerySourceReferenceExpression).ReferencedQuerySource.ItemName;
                }
                else
                {
                    var visitResult = VisitMemberExpression(m);
                    if (visitResult is SelectVariableNameExpression)
                    {
                        itemName = (visitResult as SelectVariableNameExpression).Name;
                    }
                }
            }
            if (itemName == null)
            {
                return(false);
            }
            var constantExpression = right as ConstantExpression;

            if (constantExpression == null)
            {
                return(false);
            }
            string address = null;

            if (propertyHint.MappingType == PropertyMappingType.Id)
            {
                address = MakeResourceAddress(GetPropertyInfo(left), constantExpression.Value.ToString());
            }
            else if (propertyHint.MappingType == PropertyMappingType.Address)
            {
                address = constantExpression.Value.ToString();
            }
            if (address != null)
            {
                if (QueryBuilder.SelectVariables.Contains(itemName))
                {
                    QueryBuilder.AddFilterExpression(String.Format("(?{0}=<{1}>)", itemName, address));
                }
                else
                {
                    QueryBuilder.ConvertVariableToConstantUri(itemName, address);
                }
                return(true);
            }
            return(false);
        }
 public ExportAttribute(PropertyHint hint = PropertyHint.None, string hintString = "")
 {
     this.hint       = hint;
     this.hintString = hintString;
 }
 private void AppendPropertyConstraint(string sourceVar, PropertyHint propertyHint,
                                       ConstantExpression constantExpression)
 {
     QueryBuilder.AddTripleConstraint(GraphNode.Variable, sourceVar, GraphNode.Iri, propertyHint.SchemaTypeUri, GraphNode.Raw, QueryBuilder.MakeSparqlConstant(constantExpression.Value, false));
 }
            static bool GetStringArrayEnumHint(VariantType elementVariantType,
                                               AttributeData exportAttr, out string?hintString)
            {
                var constructorArguments = exportAttr.ConstructorArguments;

                if (constructorArguments.Length > 0)
                {
                    var presetHintValue = exportAttr.ConstructorArguments[0].Value;

                    PropertyHint presetHint = presetHintValue switch
                    {
                        null => PropertyHint.None,
                        int intValue => (PropertyHint)intValue,
                        _ => (PropertyHint)(long)presetHintValue
                    };

                    if (presetHint == PropertyHint.Enum)
                    {
                        string?presetHintString = constructorArguments.Length > 1 ?
                                                  exportAttr.ConstructorArguments[1].Value?.ToString() :
                                                  null;

                        hintString = (int)elementVariantType + "/" + (int)PropertyHint.Enum + ":";

                        if (presetHintString != null)
                        {
                            hintString += presetHintString;
                        }

                        return(true);
                    }
                }

                hintString = null;
                return(false);
            }

            if (!isTypeArgument && variantType == VariantType.Array)
            {
                var elementType = MarshalUtils.GetArrayElementType(type);

                if (elementType == null)
                {
                    return(false); // Non-generic Array, so there's no hint to add
                }
                var elementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementType, typeCache) !.Value;
                var elementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(elementMarshalType) !.Value;

                bool isPresetHint = false;

                if (elementVariantType == VariantType.String)
                {
                    isPresetHint = GetStringArrayEnumHint(elementVariantType, exportAttr, out hintString);
                }

                if (!isPresetHint)
                {
                    bool hintRes = TryGetMemberExportHint(typeCache, elementType,
                                                          exportAttr, elementVariantType, isTypeArgument: true,
                                                          out var elementHint, out var elementHintString);

                    // Format: type/hint:hint_string
                    if (hintRes)
                    {
                        hintString = (int)elementVariantType + "/" + (int)elementHint + ":";

                        if (elementHintString != null)
                        {
                            hintString += elementHintString;
                        }
                    }
                    else
                    {
                        hintString = (int)elementVariantType + "/" + (int)PropertyHint.None + ":";
                    }
                }

                hint = PropertyHint.TypeString;

                return(hintString != null);
            }

            if (!isTypeArgument && variantType == VariantType.PackedStringArray)
            {
                if (GetStringArrayEnumHint(VariantType.String, exportAttr, out hintString))
                {
                    hint = PropertyHint.TypeString;
                    return(true);
                }
            }

            if (!isTypeArgument && variantType == VariantType.Dictionary)
            {
                // TODO: Dictionaries are not supported in the inspector
                return(false);
            }

            return(false);
        }
        private static bool TryGetMemberExportHint(
            MarshalUtils.TypeCache typeCache,
            ITypeSymbol type, AttributeData exportAttr,
            VariantType variantType, bool isTypeArgument,
            out PropertyHint hint, out string?hintString
            )
        {
            hint       = PropertyHint.None;
            hintString = null;

            if (variantType == VariantType.Nil)
            {
                return(true); // Variant, no export hint
            }
            if (variantType == VariantType.Int &&
                type.IsValueType && type.TypeKind == TypeKind.Enum)
            {
                bool hasFlagsAttr = type.GetAttributes()
                                    .Any(a => a.AttributeClass?.IsSystemFlagsAttribute() ?? false);

                hint = hasFlagsAttr ? PropertyHint.Flags : PropertyHint.Enum;

                var members = type.GetMembers();

                var enumFields = members
                                 .Where(s => s.Kind == SymbolKind.Field && s.IsStatic &&
                                        s.DeclaredAccessibility == Accessibility.Public &&
                                        !s.IsImplicitlyDeclared)
                                 .Cast <IFieldSymbol>().ToArray();

                var hintStringBuilder         = new StringBuilder();
                var nameOnlyHintStringBuilder = new StringBuilder();

                // True: enum Foo { Bar, Baz, Qux }
                // True: enum Foo { Bar = 0, Baz = 1, Qux = 2 }
                // False: enum Foo { Bar = 0, Baz = 7, Qux = 5 }
                bool usesDefaultValues = true;

                for (int i = 0; i < enumFields.Length; i++)
                {
                    var enumField = enumFields[i];

                    if (i > 0)
                    {
                        hintStringBuilder.Append(",");
                        nameOnlyHintStringBuilder.Append(",");
                    }

                    string enumFieldName = enumField.Name;
                    hintStringBuilder.Append(enumFieldName);
                    nameOnlyHintStringBuilder.Append(enumFieldName);

                    long val = enumField.ConstantValue switch
                    {
                        sbyte v => v,
                        short v => v,
                        int v => v,
                        long v => v,
                        byte v => v,
                        ushort v => v,
                        uint v => v,
                        ulong v => (long)v,
                        _ => 0
                    };

                    uint expectedVal = (uint)(hint == PropertyHint.Flags ? 1 << i : i);
                    if (val != expectedVal)
                    {
                        usesDefaultValues = false;
                    }

                    hintStringBuilder.Append(":");
                    hintStringBuilder.Append(val);
                }

                hintString = !usesDefaultValues?
                             hintStringBuilder.ToString() :
                                 // If we use the format NAME:VAL, that's what the editor displays.
                                 // That's annoying if the user is not using custom values for the enum constants.
                                 // This may not be needed in the future if the editor is changed to not display values.
                                 nameOnlyHintStringBuilder.ToString();

                return(true);
            }

            if (variantType == VariantType.Object && type is INamedTypeSymbol memberNamedType)
            {
                if (memberNamedType.InheritsFrom("GodotSharp", "Godot.Resource"))
                {
                    string nativeTypeName = memberNamedType.GetGodotScriptNativeClassName() !;

                    hint       = PropertyHint.ResourceType;
                    hintString = nativeTypeName;

                    return(true);
                }

                if (memberNamedType.InheritsFrom("GodotSharp", "Godot.Node"))
                {
                    string nativeTypeName = memberNamedType.GetGodotScriptNativeClassName() !;

                    hint       = PropertyHint.NodeType;
                    hintString = nativeTypeName;

                    return(true);
                }
            }