public static IEnumerable <CodeParameterDeclarationExpression> Parameters(this ICodeDelegate method)
 {
     return(method.Parameters.OfType <CodeParameterDeclarationExpression>());
 }
Beispiel #2
0
 private CodeTypeContainer GetDBusType(string type, CodeNamespace @namespace, ICodeDelegate @delegate = null)
 {
     using (var sr = new StringReader(type))
         return(GetNextDBusType(sr, new Stack <CodeTypeContainer>(), @namespace, @delegate));
 }
Beispiel #3
0
        private CodeTypeContainer GetNextDBusType(StringReader sr, Stack <CodeTypeContainer> containers, CodeNamespace @namespace, ICodeDelegate @delegate)
        {
            CodeTypeContainer container;
            int code;

            switch (code = sr.Read())
            {
            case '(':     // STRUCT
                container = CodeTypeContainer.CreateStruct();
                containers.Push(container);

                var i = 1;
                do
                {
                    var type = GetNextDBusType(sr, containers, @namespace, @delegate);

                    // Seeing ourselves signals that we are complete
                    if (type == container)
                    {
                        break;
                    }

                    // Add each member as a property
                    var property = Declare.Property("Item" + i++, type.Reference);
                    container.Members.Add(property.BackingField);
                    container.Members.Add(property);
                } while (true);

                // Empty structures are not allowed; there must be at least one type code between
                // the parentheses. [1]
                // [1] http://dbus.freedesktop.org/doc/dbus-specification.html#container-types
                if (container.Members.Count == 0)
                {
                    throw new InvalidDataException("Empty structures are not allowed; " +
                                                   "there must be at least one type code between the parentheses.");
                }

                var j    = 2;
                var name = @delegate.Name + "Data";
                while (@namespace.ContainsTypeName(name))
                {
                    name = @delegate.Name + "Data" + j++;
                }
                container.Name = name;
                @namespace.Types.Add(container);

                return(container);

            case 'a':     // ARRAY
                container = CodeTypeContainer.CreateArray();
                containers.Push(container);

                // The array type code must be followed by a single complete type. [1]
                var nextType = GetNextDBusType(sr, containers, @namespace, @delegate);
                if (GetContainerType(nextType) == Container.DictEntryArray && !nextType.IsComplete)
                {
                    nextType.IsComplete = true;
                    return(nextType);
                }

                containers.Pop();
                container.SetArrayElementType(nextType);

                return(container);

            case '{':     // DICT_ENTRY
                // Implementations must not accept dict entries outside of arrays... [1]
                if (GetContainerType(containers.Pop()) != Container.Array)
                {
                    throw new InvalidDataException("DICT_ENTRY must occur in an array. e.g.: type=\"a{us}\"");
                }

                container = CodeTypeContainer.CreateIDictionary();
                containers.Push(container);

                var key = GetNextDBusType(sr, containers, @namespace, @delegate);

                // ...the first single complete type (the "key") must be a basic type rather than
                // a container type. [1]
                if (GetContainerType(key) != Container.None && key.Name != typeof(object).ToString())
                {
                    throw new InvalidDataException("The key for DICT_ENTRY must be a basic type.");
                }

                var value = GetNextDBusType(sr, containers, @namespace, @delegate);

                container.TypeArguments.Add(key.Reference);
                container.TypeArguments.Add(value.Reference);
                containers.Pop();

                ImportNamespaces(container.RequiredImports);

                return(container);

            case ')':     // STRUCT closing delimiter
                return(containers.Pop());

            case '}':     // DICT_ENTRY closing delimiter
                return(containers.Pop());

            case -1:     // Stream end
                Messenger.SendWarning(this, "Reached end of stream.");
                return(containers.Pop());

            default:     // Basic types
                return(GetBasicType(code));
            }
        }
Beispiel #4
0
        private void ProcessArgs(DBusItemCollection items, ICodeDelegate @delegate, CodeNamespace @namespace)
        {
            var hasReturnType = false;
            var p             = 0;

            foreach (var item in items)
            {
                switch (item.DBusItemType)
                {
                case DBusItemType.Arg:
                    var arg  = (Arg)item;
                    var type = GetDBusType(arg.Type, @namespace, @delegate);

                    var declaration = new CodeParameterDeclarationExpression();
                    declaration.Type = type.Reference;

                    if (arg.Parent is Signal)
                    {
                        // Even though signal args are always out, DBusSharp allows us to treat them as in
                        declaration.Direction = FieldDirection.In;
                    }
                    else
                    {
                        declaration.Direction = arg.Direction == Direction.In ?
                                                FieldDirection.In : FieldDirection.Out;
                    }

                    // Becomes the return type if we don't have one yet
                    if (declaration.Direction == FieldDirection.Out && !hasReturnType)
                    {
                        @delegate.ReturnType = declaration.Type;
                        hasReturnType        = true;

                        if (!string.IsNullOrWhiteSpace(arg.Name))
                        {
                            var argumentAttribute = Declare.Attribute("Argument", arg.Name);
                            ImportNamespace("DBus");
                            var method = (CodeMemberMethod)@delegate;
                            method.ReturnTypeCustomAttributes.Add(argumentAttribute);
                        }
                    }
                    else
                    {
                        var name = arg.Name;
                        if (string.IsNullOrWhiteSpace(name))
                        {
                            name = "arg" + p++;
                        }

                        var parameters = @delegate.Parameters();
                        var n          = 2;
                        while (parameters.Any(c => name == c.Name))
                        {
                            name += n++;
                        }

                        declaration.Name = name;

                        @delegate.Parameters.Add(declaration);
                    }
                    break;

                case DBusItemType.Annotation:
                    var attribute = ReadAnnotation((Annotation)item, @namespace);
                    @delegate.CustomAttributes.Add(attribute);
                    break;

                default:
                    throw CreateInvalidDataException(item.DBusItemType, DBusItemType.Arg, DBusItemType.Annotation);
                }
            }
        }