diff --git a/Avalonia.Desktop.slnf b/Avalonia.Desktop.slnf
index 914a74c27e..b32d6e3d70 100644
--- a/Avalonia.Desktop.slnf
+++ b/Avalonia.Desktop.slnf
@@ -41,7 +41,6 @@
"src\\Linux\\Avalonia.LinuxFramebuffer\\Avalonia.LinuxFramebuffer.csproj",
"src\\Linux\\Tmds.DBus.Protocol\\Tmds.DBus.Protocol.csproj",
"src\\Linux\\Tmds.DBus.SourceGenerator\\Tmds.DBus.SourceGenerator.csproj",
- "src\\Linux\\Tmds.DBus\\Tmds.DBus.csproj",
"src\\Markup\\Avalonia.Markup.Xaml.Loader\\Avalonia.Markup.Xaml.Loader.csproj",
"src\\Markup\\Avalonia.Markup.Xaml\\Avalonia.Markup.Xaml.csproj",
"src\\Markup\\Avalonia.Markup\\Avalonia.Markup.csproj",
diff --git a/Avalonia.sln b/Avalonia.sln
index 8c4ad8b03e..36f88e3592 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -306,8 +306,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tmds.DBus.Protocol", "src\L
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tmds.DBus.SourceGenerator", "src\Linux\Tmds.DBus.SourceGenerator\Tmds.DBus.SourceGenerator.csproj", "{FFE8B040-B467-424A-9DDB-6155DC1EB62E}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tmds.DBus", "src\Linux\Tmds.DBus\Tmds.DBus.csproj", "{1ABAB94E-D687-4E3B-8489-39EDCFA91653}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -716,10 +714,6 @@ Global
{FFE8B040-B467-424A-9DDB-6155DC1EB62E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FFE8B040-B467-424A-9DDB-6155DC1EB62E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFE8B040-B467-424A-9DDB-6155DC1EB62E}.Release|Any CPU.Build.0 = Release|Any CPU
- {1ABAB94E-D687-4E3B-8489-39EDCFA91653}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1ABAB94E-D687-4E3B-8489-39EDCFA91653}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1ABAB94E-D687-4E3B-8489-39EDCFA91653}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1ABAB94E-D687-4E3B-8489-39EDCFA91653}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -809,7 +803,6 @@ Global
{9AE1B827-21AC-4063-AB22-C8804B7F931E} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{18B242C7-33BC-4B40-B12C-82B20F2BF638} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{FFE8B040-B467-424A-9DDB-6155DC1EB62E} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
- {1ABAB94E-D687-4E3B-8489-39EDCFA91653} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj b/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
index 168ad8b82a..995c57dc64 100644
--- a/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
+++ b/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
@@ -20,8 +20,6 @@
OutputItemType="Analyzer"
ReferenceOutputAssembly="false"
PrivateAssets="all"/>
-
-
diff --git a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs
index 94709926e7..8cb5d5761c 100644
--- a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs
+++ b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs
@@ -45,7 +45,7 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
public ValueTask WatchForwardKeyAsync(Action handler) =>
_old?.WatchForwardKeyAsync(handler)
- ?? _modern?.WatchForwardKeyAsync((e, ev) => handler.Invoke(e, (ev.keyval, ev.state, ev.type ? 1 : 0)))
+ ?? _modern?.WatchForwardKeyAsync((e, ev) => handler.Invoke(e, (ev.Keyval, ev.State, ev.Type ? 1 : 0)))
?? new ValueTask(Disposable.Empty);
public ValueTask WatchUpdateFormattedPreeditAsync(
@@ -53,7 +53,7 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
_old?.WatchUpdateFormattedPreeditAsync(handler!)
?? _modern?.WatchUpdateFormattedPreeditAsync(handler!)
?? new ValueTask(Disposable.Empty);
-
+
public Task SetCapacityAsync(uint flags) =>
_old?.SetCapacityAsync(flags) ?? _modern?.SetCapabilityAsync(flags) ?? Task.CompletedTask;
}
diff --git a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs
index efd173d9a6..eaa5c8f13e 100644
--- a/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs
+++ b/src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs
@@ -29,7 +29,7 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
var resp = await method.CreateICv3Async(GetAppName(),
Process.GetCurrentProcess().Id);
- var proxy = new OrgFcitxFcitxInputContext(Connection, name, $"/inputcontext_{resp.icid}");
+ var proxy = new OrgFcitxFcitxInputContext(Connection, name, $"/inputcontext_{resp.Icid}");
_context = new FcitxICWrapper(proxy);
}
else
diff --git a/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs b/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs
index 35dc18288a..d81d2d7394 100644
--- a/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs
+++ b/src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs
@@ -51,17 +51,16 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus
Client.SetPreeditText(_preeditText, _preeditText == null ? null : _preeditCursor);
}
- private void OnUpdatePreedit(Exception? arg1, (DBusVariantItem text, uint cursor_pos, bool visible) preeditComponents)
+ private void OnUpdatePreedit(Exception? arg1, (VariantValue Text, uint CursorPos, bool Visible) preeditComponents)
{
- if (preeditComponents.text is { Value: DBusStructItem { Count: >= 3 } structItem } &&
- structItem[2] is DBusStringItem stringItem)
+ if (preeditComponents.Text is { Type: VariantValueType.Struct, Count: >= 3 } structItem && structItem.GetItem(2) is { Type: VariantValueType.String} stringItem)
{
- _preeditText = stringItem.Value;
+ _preeditText = stringItem.GetString();
_preeditCursor = _preeditText != null
? Utf16Utils.CharacterOffsetToStringOffset(_preeditText,
- (int)Math.Min(preeditComponents.cursor_pos, int.MaxValue), false)
+ (int)Math.Min(preeditComponents.CursorPos, int.MaxValue), false)
: 0;
-
+
_preeditShown = true;
}
else
@@ -102,13 +101,13 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus
});
}
- private void OnCommitText(Exception? e, DBusVariantItem variantItem)
+ private void OnCommitText(Exception? e, VariantValue variantItem)
{
- if (_insideReset > 0)
+ if (_insideReset > 0)
{
// For some reason iBus can trigger a CommitText while being reset.
// Thankfully the signal is sent _during_ Reset call processing,
- // so it arrives on-the-wire before Reset call result, so we can
+ // so it arrives on-the-wire before Reset call result, so we can
// check if we have any pending Reset calls and ignore the signal here
return;
}
@@ -118,8 +117,8 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus
return;
}
- if (variantItem.Value is DBusStructItem { Count: >= 3 } structItem && structItem[2] is DBusStringItem stringItem)
- FireCommit(stringItem.Value);
+ if (variantItem.Count >= 3 && variantItem.GetItem(2) is { Type: VariantValueType.String } stringItem)
+ FireCommit(stringItem.GetString());
}
protected override Task DisconnectAsync() => _service?.DestroyAsync() ?? Task.CompletedTask;
diff --git a/src/Avalonia.FreeDesktop/DBusMenuExporter.cs b/src/Avalonia.FreeDesktop/DBusMenuExporter.cs
index fcc118bd31..beb949536f 100644
--- a/src/Avalonia.FreeDesktop/DBusMenuExporter.cs
+++ b/src/Avalonia.FreeDesktop/DBusMenuExporter.cs
@@ -60,17 +60,14 @@ namespace Avalonia.FreeDesktop
private void InitBackingProperties()
{
- BackingProperties.Version = 4;
- BackingProperties.Status = string.Empty;
- BackingProperties.TextDirection = string.Empty;
- BackingProperties.IconThemePath = Array.Empty();
+ Version = 4;
}
protected override Connection Connection { get; }
public override string Path { get; }
- protected override ValueTask<(uint revision, (int, Dictionary, DBusVariantItem[]) layout)> OnGetLayoutAsync(int parentId, int recursionDepth, string[] propertyNames)
+ protected override ValueTask<(uint Revision, (int, Dictionary, Variant[]) Layout)> OnGetLayoutAsync(int parentId, int recursionDepth, string[] propertyNames)
{
var menu = GetMenu(parentId);
var layout = GetLayout(menu.item, menu.menu, recursionDepth, propertyNames);
@@ -80,22 +77,22 @@ namespace Avalonia.FreeDesktop
OnIsNativeMenuExportedChanged?.Invoke(this, EventArgs.Empty);
}
- return new ValueTask<(uint, (int, Dictionary, DBusVariantItem[]))>((_revision, layout));
+ return new ValueTask<(uint, (int, Dictionary, Variant[]))>((_revision, layout));
}
- protected override ValueTask<(int, Dictionary)[]> OnGetGroupPropertiesAsync(int[] ids, string[] propertyNames)
+ protected override ValueTask<(int, Dictionary)[]> OnGetGroupPropertiesAsync(int[] ids, string[] propertyNames)
=> new(ids.Select(id => (id, GetProperties(GetMenu(id), propertyNames))).ToArray());
- protected override ValueTask OnGetPropertyAsync(int id, string name) =>
- new(GetProperty(GetMenu(id), name) ?? new DBusVariantItem("i", new DBusInt32Item(0)));
+ protected override ValueTask OnGetPropertyAsync(int id, string name) =>
+ new(GetProperty(GetMenu(id), name) ?? new Variant(0));
- protected override ValueTask OnEventAsync(int id, string eventId, DBusVariantItem data, uint timestamp)
+ protected override ValueTask OnEventAsync(int id, string eventId, VariantValue data, uint timestamp)
{
HandleEvent(id, eventId);
return new ValueTask();
}
- protected override ValueTask OnEventGroupAsync((int, string, DBusVariantItem, uint)[] events)
+ protected override ValueTask OnEventGroupAsync((int, string, VariantValue, uint)[] events)
{
foreach (var e in events)
HandleEvent(e.Item1, e.Item2);
@@ -104,7 +101,7 @@ namespace Avalonia.FreeDesktop
protected override ValueTask OnAboutToShowAsync(int id) => new(false);
- protected override ValueTask<(int[] updatesNeeded, int[] idErrors)> OnAboutToShowGroupAsync(int[] ids) =>
+ protected override ValueTask<(int[] UpdatesNeeded, int[] IdErrors)> OnAboutToShowGroupAsync(int[] ids) =>
new((Array.Empty(), Array.Empty()));
private async Task InitializeAsync()
@@ -220,35 +217,32 @@ namespace Avalonia.FreeDesktop
"type", "label", "enabled", "visible", "shortcut", "toggle-type", "children-display", "toggle-state", "icon-data"
};
- private static DBusVariantItem? GetProperty((NativeMenuItemBase? item, NativeMenu? menu) i, string name)
+ private static Variant? GetProperty((NativeMenuItemBase? item, NativeMenu? menu) i, string name)
{
var (it, menu) = i;
if (it is NativeMenuItemSeparator)
{
if (name == "type")
- return new DBusVariantItem("s", new DBusStringItem("separator"));
+ return new Variant("separator");
}
else if (it is NativeMenuItem item)
{
if (name == "type")
return null;
if (name == "label")
- return new DBusVariantItem("s", new DBusStringItem(item.Header ?? ""));
+ return new Variant(item.Header ?? "");
if (name == "enabled")
{
if (item.Menu is not null && item.Menu.Items.Count == 0)
- return new DBusVariantItem("b", new DBusBoolItem(false));
+ return new Variant(false);
if (!item.IsEnabled)
- return new DBusVariantItem("b", new DBusBoolItem(false));
+ return new Variant(false);
return null;
}
- if (name == "visible") {
- if (!item.IsVisible)
- return new DBusVariantItem("b", new DBusBoolItem(false));
- return new DBusVariantItem("b", new DBusBoolItem(true));
- }
+ if (name == "visible")
+ return new Variant(item.IsVisible);
if (name == "shortcut")
{
@@ -256,30 +250,30 @@ namespace Avalonia.FreeDesktop
return null;
if (item.Gesture.KeyModifiers == 0)
return null;
- var lst = new List();
+ var lst = new Array();
var mod = item.Gesture;
if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Control))
- lst.Add(new DBusStringItem("Control"));
+ lst.Add(new Variant("Control"));
if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Alt))
- lst.Add(new DBusStringItem("Alt"));
+ lst.Add(new Variant("Alt"));
if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Shift))
- lst.Add(new DBusStringItem("Shift"));
+ lst.Add(new Variant("Shift"));
if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Meta))
- lst.Add(new DBusStringItem("Super"));
- lst.Add(new DBusStringItem(item.Gesture.Key.ToString()));
- return new DBusVariantItem("aas", new DBusArrayItem(DBusType.Array, new[] { new DBusArrayItem(DBusType.String, lst) }));
+ lst.Add(new Variant("Super"));
+ lst.Add(new Variant(item.Gesture.Key.ToString()));
+ return Variant.FromArray(new Array>(new[] { lst }));
}
if (name == "toggle-type")
{
if (item.ToggleType == NativeMenuItemToggleType.CheckBox)
- return new DBusVariantItem("s", new DBusStringItem("checkmark"));
+ return new Variant("checkmark");
if (item.ToggleType == NativeMenuItemToggleType.Radio)
- return new DBusVariantItem("s", new DBusStringItem("radio"));
+ return new Variant("radio");
}
if (name == "toggle-state" && item.ToggleType != NativeMenuItemToggleType.None)
- return new DBusVariantItem("i", new DBusInt32Item(item.IsChecked ? 1 : 0));
+ return new Variant(item.IsChecked ? 1 : 0);
if (name == "icon-data")
{
@@ -292,50 +286,49 @@ namespace Avalonia.FreeDesktop
var icon = loader.LoadIcon(item.Icon.PlatformImpl.Item);
using var ms = new MemoryStream();
icon.Save(ms);
- return new DBusVariantItem("ay", new DBusByteArrayItem(ms.ToArray()));
+ return Variant.FromArray(new Array(ms.ToArray()));
}
}
}
if (name == "children-display")
- return menu is not null ? new DBusVariantItem("s", new DBusStringItem("submenu")) : null;
+ {
+ if (menu is not null)
+ return new Variant("submenu");
+ return null;
+ }
}
return null;
}
- private static Dictionary GetProperties((NativeMenuItemBase? item, NativeMenu? menu) i, string[] names)
+ private static Dictionary GetProperties((NativeMenuItemBase? item, NativeMenu? menu) i, string[] names)
{
if (names.Length == 0)
names = s_allProperties;
- var properties = new Dictionary();
+ var properties = new Dictionary();
foreach (var n in names)
{
var v = GetProperty(i, n);
- if (v is not null)
- properties.Add(n, v);
+ if (v.HasValue)
+ properties.Add(n, v.Value);
}
return properties;
}
- private (int, Dictionary, DBusVariantItem[]) GetLayout(NativeMenuItemBase? item, NativeMenu? menu, int depth, string[] propertyNames)
+ private (int, Dictionary, Variant[]) GetLayout(NativeMenuItemBase? item, NativeMenu? menu, int depth, string[] propertyNames)
{
var id = item is null ? 0 : GetId(item);
var props = GetProperties((item, menu), propertyNames);
- var children = depth == 0 || menu is null ? Array.Empty() : new DBusVariantItem[menu.Items.Count];
+ var children = depth == 0 || menu is null ? Array.Empty() : new Variant[menu.Items.Count];
if (menu is not null)
{
for (var c = 0; c < children.Length; c++)
{
var ch = menu.Items[c];
var layout = GetLayout(ch, (ch as NativeMenuItem)?.Menu, depth == -1 ? -1 : depth - 1, propertyNames);
- children[c] = new DBusVariantItem("(ia{sv}av)", new DBusStructItem(new DBusItem[]
- {
- new DBusInt32Item(layout.Item1),
- new DBusArrayItem(DBusType.DictEntry, layout.Item2.Select(static x => new DBusDictEntryItem(new DBusStringItem(x.Key), x.Value)).ToArray()),
- new DBusArrayItem(DBusType.Variant, layout.Item3)
- }));
+ children[c] = Variant.FromStruct(Struct.Create(layout.Item1, new Dict(layout.Item2), new Array(layout.Item3)));
}
}
diff --git a/src/Avalonia.FreeDesktop/DBusPlatformSettings.cs b/src/Avalonia.FreeDesktop/DBusPlatformSettings.cs
index 852ed90764..acfa985e90 100644
--- a/src/Avalonia.FreeDesktop/DBusPlatformSettings.cs
+++ b/src/Avalonia.FreeDesktop/DBusPlatformSettings.cs
@@ -41,14 +41,12 @@ namespace Avalonia.FreeDesktop
try
{
var version = await _settings!.GetVersionPropertyAsync();
- DBusVariantItem value;
+ VariantValue value;
if (version >= 2)
value = await _settings!.ReadOneAsync("org.freedesktop.appearance", "color-scheme");
else
- value = (DBusVariantItem)(await _settings!.ReadAsync("org.freedesktop.appearance", "color-scheme")).Value;
- if (value.Value is DBusUInt32Item dBusUInt32Item)
- return ToColorScheme(dBusUInt32Item.Value);
- return null;
+ value = (await _settings!.ReadAsync("org.freedesktop.appearance", "color-scheme")).GetItem(0);
+ return ToColorScheme(value.GetUInt32());
}
catch (DBusException)
{
@@ -61,14 +59,12 @@ namespace Avalonia.FreeDesktop
try
{
var version = await _settings!.GetVersionPropertyAsync();
- DBusVariantItem value;
+ VariantValue value;
if (version >= 2)
value = await _settings!.ReadOneAsync("org.freedesktop.appearance", "accent-color");
else
- value = (DBusVariantItem)(await _settings!.ReadAsync("org.freedesktop.appearance", "accent-color")).Value;
- if (value.Value is DBusStructItem dBusStructItem)
- return ToAccentColor(dBusStructItem);
- return null;
+ value = (await _settings!.ReadAsync("org.freedesktop.appearance", "accent-color")).GetItem(0);
+ return ToAccentColor(value);
}
catch (DBusException)
{
@@ -76,20 +72,20 @@ namespace Avalonia.FreeDesktop
}
}
- private void SettingsChangedHandler(Exception? exception, (string @namespace, string key, DBusVariantItem value) valueTuple)
+ private void SettingsChangedHandler(Exception? exception, (string Namespace, string Key, VariantValue Value) tuple)
{
if (exception is not null)
return;
- switch (valueTuple)
+ switch (tuple)
{
- case ("org.freedesktop.appearance", "color-scheme", { } colorScheme):
- _themeVariant = ToColorScheme((colorScheme.Value as DBusUInt32Item)!.Value);
+ case ("org.freedesktop.appearance", "color-scheme", var colorScheme):
+ _themeVariant = ToColorScheme(colorScheme.GetUInt32());
_lastColorValues = BuildPlatformColorValues();
OnColorValuesChanged(_lastColorValues!);
break;
- case ("org.freedesktop.appearance", "accent-color", { } accentColor):
- _accentColor = ToAccentColor((accentColor.Value as DBusStructItem)!);
+ case ("org.freedesktop.appearance", "accent-color", var accentColor):
+ _accentColor = ToAccentColor(accentColor);
_lastColorValues = BuildPlatformColorValues();
OnColorValuesChanged(_lastColorValues!);
break;
@@ -118,16 +114,16 @@ namespace Avalonia.FreeDesktop
return isDark ? PlatformThemeVariant.Dark : PlatformThemeVariant.Light;
}
- private static Color? ToAccentColor(DBusStructItem value)
+ private static Color? ToAccentColor(VariantValue value)
{
/*
Indicates the system's preferred accent color as a tuple of RGB values
in the sRGB color space, in the range [0,1].
Out-of-range RGB values should be treated as an unset accent color.
*/
- var r = (value[0] as DBusDoubleItem)!.Value;
- var g = (value[1] as DBusDoubleItem)!.Value;
- var b = (value[2] as DBusDoubleItem)!.Value;
+ var r = value.GetItem(0).GetDouble();
+ var g = value.GetItem(1).GetDouble();
+ var b = value.GetItem(2).GetDouble();
if (r is < 0 or > 1 || g is < 0 or > 1 || b is < 0 or > 1)
return null;
return Color.FromRgb((byte)(r * 255), (byte)(g * 255), (byte)(b * 255));
diff --git a/src/Avalonia.FreeDesktop/DBusSystemDialog.cs b/src/Avalonia.FreeDesktop/DBusSystemDialog.cs
index 7ee963fc17..bd041a044a 100644
--- a/src/Avalonia.FreeDesktop/DBusSystemDialog.cs
+++ b/src/Avalonia.FreeDesktop/DBusSystemDialog.cs
@@ -56,14 +56,15 @@ namespace Avalonia.FreeDesktop
{
var parentWindow = $"x11:{_handle.Handle:X}";
ObjectPath objectPath;
- var chooserOptions = new Dictionary();
- var filters = ParseFilters(options.FileTypeFilter);
- if (filters is not null)
+ var chooserOptions = new Dictionary();
+
+ if (TryParseFilters(options.FileTypeFilter, out var filters))
chooserOptions.Add("filters", filters);
if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath)
- chooserOptions.Add("current_folder", new DBusVariantItem("ay", new DBusByteArrayItem(Encoding.UTF8.GetBytes(folderPath + "\0"))));
- chooserOptions.Add("multiple", new DBusVariantItem("b", new DBusBoolItem(options.AllowMultiple)));
+ chooserOptions.Add("current_folder", Variant.FromArray(new Array(Encoding.UTF8.GetBytes(folderPath + "\0"))));
+
+ chooserOptions.Add("multiple", new Variant(options.AllowMultiple));
objectPath = await _fileChooser.OpenFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions);
@@ -74,7 +75,7 @@ namespace Avalonia.FreeDesktop
if (e is not null)
tsc.TrySetException(e);
else
- tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray());
+ tsc.TrySetResult(x.Results["uris"].GetArray());
});
var uris = await tsc.Task ?? Array.Empty();
@@ -85,15 +86,14 @@ namespace Avalonia.FreeDesktop
{
var parentWindow = $"x11:{_handle.Handle:X}";
ObjectPath objectPath;
- var chooserOptions = new Dictionary();
- var filters = ParseFilters(options.FileTypeChoices);
- if (filters is not null)
+ var chooserOptions = new Dictionary();
+ if (TryParseFilters(options.FileTypeChoices, out var filters))
chooserOptions.Add("filters", filters);
if (options.SuggestedFileName is { } currentName)
- chooserOptions.Add("current_name", new DBusVariantItem("s", new DBusStringItem(currentName)));
+ chooserOptions.Add("current_name", new Variant(currentName));
if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath)
- chooserOptions.Add("current_folder", new DBusVariantItem("ay", new DBusByteArrayItem(Encoding.UTF8.GetBytes(folderPath + "\0"))));
+ chooserOptions.Add("current_folder", Variant.FromArray(new Array(Encoding.UTF8.GetBytes(folderPath + "\0"))));
objectPath = await _fileChooser.SaveFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions);
var request = new OrgFreedesktopPortalRequest(_connection, "org.freedesktop.portal.Desktop", objectPath);
@@ -102,41 +102,31 @@ namespace Avalonia.FreeDesktop
using var disposable = await request.WatchResponseAsync((e, x) =>
{
if (e is not null)
+ {
tsc.TrySetException(e);
+ }
else
{
- if(x.results.TryGetValue("current_filter", out var value))
+ if (x.Results.TryGetValue("current_filter", out var currentFilter))
{
- var currentFilter = value.Value as DBusStructItem;
- if(currentFilter != null)
+ var name = currentFilter.GetItem(0).GetString();
+ selectedType = new FilePickerFileType(name);
+ var patterns = new List();
+ var mimeTypes = new List();
+ var types = currentFilter.GetItem(1).GetArray();
+ foreach(var t in types)
{
- var name = (currentFilter[0] as DBusStringItem)?.Value.ToString() ?? "";
- selectedType = new FilePickerFileType(name);
- if(currentFilter[1] is DBusArrayItem types)
- {
- List filters = new List();
- List mimeTypes = new List();
- foreach(var t in types)
- {
- if(t is DBusStructItem filter)
- {
- if((filter[0] as DBusUInt32Item)?.Value == 1)
- {
- mimeTypes.Add((filter[1] as DBusStringItem)?.Value.ToString() ?? "");
- }
- else
- {
- filters.Add((filter[1] as DBusStringItem)?.Value.ToString() ?? "");
- }
- }
- }
-
- selectedType.Patterns = filters;
- selectedType.MimeTypes = mimeTypes;
- }
+ if (t.GetItem(0).GetUInt32() == 1)
+ mimeTypes.Add(t.GetItem(1).GetString());
+ else
+ patterns.Add(t.GetItem(1).GetString());
}
+
+ selectedType.Patterns = patterns;
+ selectedType.MimeTypes = mimeTypes;
}
- tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray());
+
+ tsc.TrySetResult(x.Results["uris"].GetArray());
}
});
@@ -157,16 +147,16 @@ namespace Avalonia.FreeDesktop
return Array.Empty();
var parentWindow = $"x11:{_handle.Handle:X}";
- var chooserOptions = new Dictionary
+ var chooserOptions = new Dictionary
{
- { "directory", new DBusVariantItem("b", new DBusBoolItem(true)) },
- { "multiple", new DBusVariantItem("b", new DBusBoolItem(options.AllowMultiple)) }
+ { "directory", new Variant(true) },
+ { "multiple", new Variant(options.AllowMultiple) }
};
if (options.SuggestedFileName is { } currentName)
- chooserOptions.Add("current_name", new DBusVariantItem("s", new DBusStringItem(currentName)));
+ chooserOptions.Add("current_name", new Variant(currentName));
if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath)
- chooserOptions.Add("current_folder", new DBusVariantItem("ay", new DBusByteArrayItem(Encoding.UTF8.GetBytes(folderPath + "\0"))));
+ chooserOptions.Add("current_folder", Variant.FromArray(new Array(Encoding.UTF8.GetBytes(folderPath + "\0"))));
var objectPath = await _fileChooser.OpenFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions);
var request = new OrgFreedesktopPortalRequest(_connection, "org.freedesktop.portal.Desktop", objectPath);
@@ -176,7 +166,7 @@ namespace Avalonia.FreeDesktop
if (e is not null)
tsc.TrySetException(e);
else
- tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray());
+ tsc.TrySetResult(x.Results["uris"].GetArray());
});
var uris = await tsc.Task ?? Array.Empty();
@@ -187,40 +177,35 @@ namespace Avalonia.FreeDesktop
.Select(static path => new BclStorageFolder(new DirectoryInfo(path))).ToList();
}
- private static DBusVariantItem? ParseFilters(IReadOnlyList? fileTypes)
+ private static bool TryParseFilters(IReadOnlyList? fileTypes, out Variant result)
{
const uint GlobStyle = 0u;
const uint MimeStyle = 1u;
// Example: [('Images', [(0, '*.ico'), (1, 'image/png')]), ('Text', [(0, '*.txt')])]
if (fileTypes is null)
- return null;
+ {
+ result = default;
+ return false;
+ }
- var filters = new List();
+ var filters = new Array>>>();
foreach (var fileType in fileTypes)
{
- var extensions = new List();
+ var extensions = new List>();
if (fileType.Patterns?.Count > 0)
- extensions.AddRange(
- fileType.Patterns.Select(static pattern =>
- new DBusStructItem(new DBusItem[] { new DBusUInt32Item(GlobStyle), new DBusStringItem(pattern) })));
+ extensions.AddRange(fileType.Patterns.Select(static pattern => Struct.Create(GlobStyle, pattern)));
else if (fileType.MimeTypes?.Count > 0)
- extensions.AddRange(
- fileType.MimeTypes.Select(static mimeType =>
- new DBusStructItem(new DBusItem[] { new DBusUInt32Item(MimeStyle), new DBusStringItem(mimeType) })));
+ extensions.AddRange(fileType.MimeTypes.Select(static mimeType => Struct.Create(MimeStyle, mimeType)));
else
continue;
- filters.Add(new DBusStructItem(
- new DBusItem[]
- {
- new DBusStringItem(fileType.Name),
- new DBusArrayItem(DBusType.Struct, extensions)
- }));
+ filters.Add(Struct.Create(fileType.Name, new Array>(extensions)));
}
- return filters.Count > 0 ? new DBusVariantItem("a(sa(us))", new DBusArrayItem(DBusType.Struct, filters)) : null;
+ result = Variant.FromArray(filters);
+ return true;
}
}
}
diff --git a/src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs b/src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs
index f7e95b83d0..8427a254c0 100644
--- a/src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs
+++ b/src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs
@@ -82,7 +82,7 @@ namespace Avalonia.FreeDesktop
if (_isDisposed || _connection is null || name != "org.kde.StatusNotifierWatcher")
return;
- if (!_serviceConnected & newOwner is not null)
+ if (!_serviceConnected && newOwner is not null)
{
_serviceConnected = true;
_statusNotifierWatcher = new OrgKdeStatusNotifierWatcher(_connection, "org.kde.StatusNotifierWatcher", "/StatusNotifierWatcher");
@@ -214,18 +214,7 @@ namespace Avalonia.FreeDesktop
public StatusNotifierItemDbusObj(Connection connection, ObjectPath dbusMenuPath)
{
Connection = connection;
- BackingProperties.Menu = dbusMenuPath;
- BackingProperties.Category = string.Empty;
- BackingProperties.Status = string.Empty;
- BackingProperties.Id = string.Empty;
- BackingProperties.Title = string.Empty;
- BackingProperties.IconPixmap = Array.Empty<(int, int, byte[])>();
- BackingProperties.AttentionIconName = string.Empty;
- BackingProperties.AttentionIconPixmap = Array.Empty<(int, int, byte[])>();
- BackingProperties.AttentionMovieName = string.Empty;
- BackingProperties.OverlayIconName = string.Empty;
- BackingProperties.OverlayIconPixmap = Array.Empty<(int, int, byte[])>();
- BackingProperties.ToolTip = (string.Empty, Array.Empty<(int, int, byte[])>(), string.Empty, string.Empty);
+ Menu = dbusMenuPath;
InvalidateAll();
}
@@ -254,12 +243,12 @@ namespace Avalonia.FreeDesktop
EmitNewAttentionIcon();
EmitNewOverlayIcon();
EmitNewToolTip();
- EmitNewStatus(BackingProperties.Status);
+ EmitNewStatus(Status);
}
public void SetIcon((int, int, byte[]) dbusPixmap)
{
- BackingProperties.IconPixmap = new[] { dbusPixmap };
+ IconPixmap = new[] { dbusPixmap };
InvalidateAll();
}
@@ -268,10 +257,10 @@ namespace Avalonia.FreeDesktop
if (text is null)
return;
- BackingProperties.Id = text;
- BackingProperties.Category = "ApplicationStatus";
- BackingProperties.Status = text;
- BackingProperties.Title = text;
+ Id = text;
+ Category = "ApplicationStatus";
+ Status = text;
+ Title = text;
InvalidateAll();
}
}
diff --git a/src/Linux/Tmds.DBus.SourceGenerator/AccessMode.cs b/src/Linux/Tmds.DBus.SourceGenerator/AccessMode.cs
new file mode 100644
index 0000000000..9348eca1d4
--- /dev/null
+++ b/src/Linux/Tmds.DBus.SourceGenerator/AccessMode.cs
@@ -0,0 +1,8 @@
+namespace Tmds.DBus.SourceGenerator
+{
+ public enum AccessMode
+ {
+ Read,
+ Write
+ }
+}
diff --git a/src/Linux/Tmds.DBus.SourceGenerator/DBusInterface.cs b/src/Linux/Tmds.DBus.SourceGenerator/DBusInterface.cs
index 07df444e97..24f1062da0 100644
--- a/src/Linux/Tmds.DBus.SourceGenerator/DBusInterface.cs
+++ b/src/Linux/Tmds.DBus.SourceGenerator/DBusInterface.cs
@@ -81,12 +81,6 @@ namespace Tmds.DBus.SourceGenerator
[XmlType(AnonymousType = true)]
public class DBusValue
{
- [XmlIgnore]
- private string? _dotNetType;
-
- [XmlIgnore]
- private string[]? _innerDotNetTypes;
-
[XmlIgnore]
private DBusType _dBusType;
@@ -99,30 +93,6 @@ namespace Tmds.DBus.SourceGenerator
[XmlAttribute("type")]
public string? Type { get; set; }
- [XmlIgnore]
- public string DotNetType
- {
- get
- {
- if (_dotNetType is not null)
- return _dotNetType;
- (_dotNetType, _innerDotNetTypes, _, _innerDBusTypes, _dBusType) = DBusSourceGenerator.ParseDBusValue(Type!);
- return _dotNetType;
- }
- }
-
- [XmlIgnore]
- public string[]? InnerDotNetTypes
- {
- get
- {
- if (_innerDotNetTypes is not null)
- return _innerDotNetTypes;
- (_dotNetType, _innerDotNetTypes, _, _innerDBusTypes, _dBusType) = DBusSourceGenerator.ParseDBusValue(Type!);
- return _innerDotNetTypes;
- }
- }
-
[XmlIgnore]
public DBusType DBusType
{
@@ -130,7 +100,7 @@ namespace Tmds.DBus.SourceGenerator
{
if (_dBusType != DBusType.Invalid)
return _dBusType;
- (_dotNetType, _innerDotNetTypes, _, _innerDBusTypes, _dBusType) = DBusSourceGenerator.ParseDBusValue(Type!);
+ (_, _innerDBusTypes, _dBusType) = DBusSourceGenerator.ParseDBusValue(Type!);
return _dBusType;
}
}
@@ -142,7 +112,7 @@ namespace Tmds.DBus.SourceGenerator
{
if (_innerDBusTypes is not null)
return _innerDBusTypes;
- (_dotNetType, _innerDotNetTypes, _, _innerDBusTypes, _dBusType) = DBusSourceGenerator.ParseDBusValue(Type!);
+ (_, _innerDBusTypes, _dBusType) = DBusSourceGenerator.ParseDBusValue(Type!);
return _innerDBusTypes;
}
}
diff --git a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Classes.cs b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Classes.cs
index efde878c52..513a56e0da 100644
--- a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Classes.cs
+++ b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Classes.cs
@@ -8,609 +8,245 @@ namespace Tmds.DBus.SourceGenerator
{
public partial class DBusSourceGenerator
{
- private static CompilationUnitSyntax MakePropertyChangesClass() => MakeCompilationUnit(
- NamespaceDeclaration(IdentifierName("Tmds.DBus.SourceGenerator"))
- .AddMembers(
- RecordDeclaration(Token(SyntaxKind.RecordKeyword), "PropertyChanges")
- .AddModifiers(Token(SyntaxKind.PublicKeyword))
- .AddTypeParameterListParameters(TypeParameter(Identifier("TProperties")))
- .AddParameterListParameters(
- Parameter(Identifier("Properties"))
- .WithType(IdentifierName("TProperties")),
- Parameter(Identifier("Invalidated"))
- .WithType(ArrayType(PredefinedType(Token(SyntaxKind.StringKeyword))).AddRankSpecifiers(ArrayRankSpecifier())),
- Parameter(Identifier("Changed"))
- .WithType(ArrayType(PredefinedType(Token(SyntaxKind.StringKeyword))).AddRankSpecifiers(ArrayRankSpecifier())))
- .WithOpenBraceToken(Token(SyntaxKind.OpenBraceToken))
- .AddMembers(
- MethodDeclaration(PredefinedType(Token(SyntaxKind.BoolKeyword)), Identifier("HasChanged"))
- .AddModifiers(Token(SyntaxKind.PublicKeyword))
- .AddParameterListParameters(
- Parameter(Identifier("property")).WithType(PredefinedType(Token(SyntaxKind.StringKeyword))))
- .WithExpressionBody(
- ArrowExpressionClause(
- BinaryExpression(SyntaxKind.NotEqualsExpression,
- InvocationExpression(
- MakeMemberAccessExpression("Array", "IndexOf"))
- .AddArgumentListArguments(
- Argument(IdentifierName("Changed")),
- Argument(IdentifierName("property"))),
- MakeLiteralExpression(-1))))
- .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
- MethodDeclaration(PredefinedType(Token(SyntaxKind.BoolKeyword)), Identifier("IsInvalidated"))
- .AddModifiers(Token(SyntaxKind.PublicKeyword))
- .AddParameterListParameters(
- Parameter(Identifier("property")).WithType(PredefinedType(Token(SyntaxKind.StringKeyword))))
- .WithExpressionBody(
- ArrowExpressionClause(
- BinaryExpression(SyntaxKind.NotEqualsExpression,
- InvocationExpression(
- MakeMemberAccessExpression("Array", "IndexOf"))
- .AddArgumentListArguments(
- Argument(IdentifierName("Invalidated")),
- Argument(IdentifierName("property"))),
- MakeLiteralExpression(-1))))
- .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)))
- .WithCloseBraceToken(Token(SyntaxKind.CloseBraceToken))));
-
- private static CompilationUnitSyntax MakeSignalHelperClass()
- {
- MethodDeclarationSyntax watchSignalMethod = MethodDeclaration(ParseTypeName("ValueTask"), "WatchSignalAsync")
- .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
- .AddParameterListParameters(
- Parameter(Identifier("connection"))
- .WithType(ParseTypeName("Connection")),
- Parameter(Identifier("rule"))
- .WithType(ParseTypeName("MatchRule")),
- Parameter(Identifier("handler"))
- .WithType(ParseTypeName("Action")),
- Parameter(Identifier("emitOnCapturedContext"))
- .WithType(PredefinedType(Token(SyntaxKind.BoolKeyword)))
- .WithDefault(EqualsValueClause(LiteralExpression(SyntaxKind.TrueLiteralExpression))))
- .WithBody(
- Block(
- ReturnStatement(
- InvocationExpression(
- MakeMemberAccessExpression("connection", "AddMatchAsync"))
- .AddArgumentListArguments(
- Argument(IdentifierName("rule")),
- Argument(
- ParenthesizedLambdaExpression()
- .AddModifiers(Token(SyntaxKind.StaticKeyword))
- .AddParameterListParameters(
- Parameter(Identifier("_")),
- Parameter(Identifier("_")))
- .WithExpressionBody(
- PostfixUnaryExpression(SyntaxKind.SuppressNullableWarningExpression,
- LiteralExpression(SyntaxKind.NullLiteralExpression)))),
- Argument(
- ParenthesizedLambdaExpression()
- .AddModifiers(Token(SyntaxKind.StaticKeyword))
- .AddParameterListParameters(
- Parameter(Identifier("e"))
- .WithType(ParseTypeName("Exception")),
- Parameter(Identifier("_"))
- .WithType(PredefinedType(Token(SyntaxKind.ObjectKeyword))),
- Parameter(Identifier("_"))
- .WithType(NullableType(PredefinedType(Token(SyntaxKind.ObjectKeyword)))),
- Parameter(Identifier("handlerState"))
- .WithType(NullableType(PredefinedType(Token(SyntaxKind.ObjectKeyword)))))
- .WithExpressionBody(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- ParenthesizedExpression(
- CastExpression(ParseTypeName("Action"),
- PostfixUnaryExpression(SyntaxKind.SuppressNullableWarningExpression,
- IdentifierName("handlerState")))),
- IdentifierName("Invoke")))
- .AddArgumentListArguments(
- Argument(IdentifierName("e"))))),
- Argument(LiteralExpression(SyntaxKind.NullLiteralExpression)),
- Argument(IdentifierName("handler")),
- Argument(IdentifierName("emitOnCapturedContext"))))));
-
- MethodDeclarationSyntax watchSignalWithReadMethod = MethodDeclaration(ParseTypeName("ValueTask"), "WatchSignalAsync")
- .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
- .AddTypeParameterListParameters(
- TypeParameter("T"))
+ private static MethodDeclarationSyntax MakeWriteNullableStringMethod() =>
+ MethodDeclaration(
+ PredefinedType(Token(SyntaxKind.VoidKeyword)),
+ "WriteNullableString")
+ .AddModifiers(
+ Token(SyntaxKind.PublicKeyword),
+ Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
- Parameter(Identifier("connection"))
- .WithType(ParseTypeName("Connection")),
- Parameter(Identifier("rule"))
- .WithType(ParseTypeName("MatchRule")),
- Parameter(Identifier("reader"))
- .WithType(ParseTypeName("MessageValueReader")),
- Parameter(Identifier("handler"))
- .WithType(ParseTypeName("Action")),
- Parameter(Identifier("emitOnCapturedContext"))
- .WithType(PredefinedType(Token(SyntaxKind.BoolKeyword)))
- .WithDefault(EqualsValueClause(LiteralExpression(SyntaxKind.TrueLiteralExpression))))
- .WithBody(
- Block(
- ReturnStatement(
- InvocationExpression(
- MakeMemberAccessExpression("connection", "AddMatchAsync"))
- .AddArgumentListArguments(
- Argument(IdentifierName("rule")),
- Argument(IdentifierName("reader")),
- Argument(
- ParenthesizedLambdaExpression()
- .AddModifiers(Token(SyntaxKind.StaticKeyword))
- .AddParameterListParameters(
- Parameter(Identifier("e")).WithType(ParseTypeName("Exception")),
- Parameter(Identifier("arg"))
- .WithType(ParseTypeName("T")),
- Parameter(Identifier("readerState"))
- .WithType(NullableType(PredefinedType(Token(SyntaxKind.ObjectKeyword)))),
- Parameter(Identifier("handlerState"))
- .WithType(NullableType(PredefinedType(Token(SyntaxKind.ObjectKeyword)))))
- .WithExpressionBody(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- ParenthesizedExpression(
- CastExpression(ParseTypeName("Action"),
- PostfixUnaryExpression(SyntaxKind.SuppressNullableWarningExpression,
- IdentifierName("handlerState")))),
- IdentifierName("Invoke")))
- .AddArgumentListArguments(
- Argument(IdentifierName("e")),
- Argument(IdentifierName("arg"))))),
- Argument(LiteralExpression(SyntaxKind.NullLiteralExpression)),
- Argument(IdentifierName("handler")),
- Argument(IdentifierName("emitOnCapturedContext"))))));
-
- MethodDeclarationSyntax watchPropertiesMethod = MethodDeclaration(ParseTypeName("ValueTask"), "WatchPropertiesChangedAsync")
- .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
- .AddTypeParameterListParameters(
- TypeParameter("T"))
+ Parameter(
+ Identifier("writer"))
+ .WithType(
+ IdentifierName("MessageWriter"))
+ .AddModifiers(
+ Token(SyntaxKind.ThisKeyword),
+ Token(SyntaxKind.RefKeyword)),
+ Parameter(
+ Identifier("value"))
+ .WithType(
+ NullableType(
+ PredefinedType(Token(SyntaxKind.StringKeyword)))))
+ .WithExpressionBody(
+ ArrowExpressionClause(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", "WriteString"))
+ .AddArgumentListArguments(
+ Argument(
+ BinaryExpression(
+ SyntaxKind.CoalesceExpression,
+ IdentifierName("value"),
+ MakeMemberAccessExpression("string", "Empty"))))))
+ .WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
+
+ private static MethodDeclarationSyntax MakeWriteObjectPathSafeMethod() =>
+ MethodDeclaration(
+ PredefinedType(Token(SyntaxKind.VoidKeyword)),
+ "WriteObjectPathSafe")
+ .AddModifiers(
+ Token(SyntaxKind.PublicKeyword),
+ Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
- Parameter(Identifier("connection"))
- .WithType(ParseTypeName("Connection")),
- Parameter(Identifier("destination"))
- .WithType(PredefinedType(Token(SyntaxKind.StringKeyword))),
- Parameter(Identifier("path"))
- .WithType(PredefinedType(Token(SyntaxKind.StringKeyword))),
- Parameter(Identifier("@interface"))
- .WithType(PredefinedType(Token(SyntaxKind.StringKeyword))),
- Parameter(Identifier("reader"))
- .WithType(ParseTypeName("MessageValueReader>")),
- Parameter(Identifier("handler"))
- .WithType(ParseTypeName("Action>")),
- Parameter(Identifier("emitOnCapturedContext"))
- .WithType(PredefinedType(Token(SyntaxKind.BoolKeyword)))
- .WithDefault(EqualsValueClause(LiteralExpression(SyntaxKind.TrueLiteralExpression))))
- .WithBody(
- Block(
- LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("MatchRule"))
- .AddVariables(
- VariableDeclarator("rule")
- .WithInitializer(
- EqualsValueClause(
- ObjectCreationExpression(ParseTypeName("MatchRule"))
- .WithInitializer(
- InitializerExpression(SyntaxKind.ObjectInitializerExpression)
- .AddExpressions(
- MakeAssignmentExpression(IdentifierName("Type"),
- MakeMemberAccessExpression("MessageType", "Signal")),
- MakeAssignmentExpression(IdentifierName("Sender"), IdentifierName("destination")),
- MakeAssignmentExpression(IdentifierName("Path"), IdentifierName("path")),
- MakeAssignmentExpression(IdentifierName("Member"),
- MakeLiteralExpression("PropertiesChanged")),
- MakeAssignmentExpression(IdentifierName("Interface"),
- MakeLiteralExpression("org.freedesktop.DBus.Properties")),
- MakeAssignmentExpression(IdentifierName("Arg0"), IdentifierName("@interface")))))))),
- ReturnStatement(
- InvocationExpression(
- IdentifierName("WatchSignalAsync"))
- .AddArgumentListArguments(
- Argument(IdentifierName("connection")),
- Argument(IdentifierName("rule")),
- Argument(IdentifierName("reader")),
- Argument(IdentifierName("handler")),
- Argument(IdentifierName("emitOnCapturedContext"))))));
-
- return MakeCompilationUnit(
- NamespaceDeclaration(IdentifierName("Tmds.DBus.SourceGenerator"))
- .AddMembers(
- ClassDeclaration("SignalHelper")
- .AddModifiers(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.StaticKeyword))
- .AddMembers(watchSignalMethod, watchSignalWithReadMethod, watchPropertiesMethod)));
- }
-
- private const string VariantExtensions = """
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using Tmds.DBus.Protocol;
-
-//
-#pragma warning disable
-#nullable enable
-namespace Tmds.DBus.SourceGenerator
-{
- internal static class VariantReader
- {
- public static DBusVariantItem ReadDBusVariant(this ref Reader reader)
- {
- ReadOnlySpan signature = reader.ReadSignature();
- SignatureReader signatureReader = new(signature);
- if (!signatureReader.TryRead(out DBusType dBusType, out ReadOnlySpan innerSignature))
- throw new InvalidOperationException("Unable to read empty variant");
- return new DBusVariantItem(Encoding.UTF8.GetString(innerSignature.ToArray()), reader.ReadDBusItem(dBusType, innerSignature));
- }
-
- private static DBusBasicTypeItem ReadDBusBasicTypeItem(this ref Reader reader, DBusType dBusType) =>
- dBusType switch
- {
- DBusType.Byte => new DBusByteItem(reader.ReadByte()),
- DBusType.Bool => new DBusBoolItem(reader.ReadBool()),
- DBusType.Int16 => new DBusInt16Item(reader.ReadInt16()),
- DBusType.UInt16 => new DBusUInt16Item(reader.ReadUInt16()),
- DBusType.Int32 => new DBusInt32Item(reader.ReadInt32()),
- DBusType.UInt32 => new DBusUInt32Item(reader.ReadUInt32()),
- DBusType.Int64 => new DBusInt64Item(reader.ReadInt64()),
- DBusType.UInt64 => new DBusUInt64Item(reader.ReadUInt64()),
- DBusType.Double => new DBusDoubleItem(reader.ReadDouble()),
- DBusType.String => new DBusStringItem(reader.ReadString()),
- DBusType.ObjectPath => new DBusObjectPathItem(reader.ReadObjectPath()),
- DBusType.Signature => new DBusSignatureItem(new Signature(reader.ReadSignature().ToString())),
- _ => throw new ArgumentOutOfRangeException(nameof(dBusType))
- };
-
- private static DBusItem ReadDBusItem(this ref Reader reader, DBusType dBusType, ReadOnlySpan innerSignature)
- {
- switch (dBusType)
- {
- case DBusType.Byte:
- return new DBusByteItem(reader.ReadByte());
- case DBusType.Bool:
- return new DBusBoolItem(reader.ReadBool());
- case DBusType.Int16:
- return new DBusInt16Item(reader.ReadInt16());
- case DBusType.UInt16:
- return new DBusUInt16Item(reader.ReadUInt16());
- case DBusType.Int32:
- return new DBusInt32Item(reader.ReadInt32());
- case DBusType.UInt32:
- return new DBusUInt32Item(reader.ReadUInt32());
- case DBusType.Int64:
- return new DBusInt64Item(reader.ReadInt64());
- case DBusType.UInt64:
- return new DBusUInt64Item(reader.ReadUInt64());
- case DBusType.Double:
- return new DBusDoubleItem(reader.ReadDouble());
- case DBusType.String:
- return new DBusStringItem(reader.ReadString());
- case DBusType.ObjectPath:
- return new DBusObjectPathItem(reader.ReadObjectPath());
- case DBusType.Signature:
- return new DBusSignatureItem(new Signature(reader.ReadSignature().ToString()));
- case DBusType.Array:
- {
- SignatureReader innerSignatureReader = new(innerSignature);
- if (!innerSignatureReader.TryRead(out DBusType innerDBusType, out ReadOnlySpan innerArraySignature))
- throw new InvalidOperationException("Failed to deserialize array item");
- List items = new();
- ArrayEnd arrayEnd = reader.ReadArrayStart(innerDBusType);
- while (reader.HasNext(arrayEnd))
- items.Add(reader.ReadDBusItem(innerDBusType, innerArraySignature));
- return new DBusArrayItem(innerDBusType, items);
- }
- case DBusType.DictEntry:
- {
- SignatureReader innerSignatureReader = new(innerSignature);
- if (!innerSignatureReader.TryRead(out DBusType innerKeyType, out ReadOnlySpan _) ||
- !innerSignatureReader.TryRead(out DBusType innerValueType, out ReadOnlySpan innerValueSignature))
- throw new InvalidOperationException($"Expected 2 inner types for DictEntry, got {Encoding.UTF8.GetString(innerSignature.ToArray())}");
- DBusBasicTypeItem key = reader.ReadDBusBasicTypeItem(innerKeyType);
- DBusItem value = reader.ReadDBusItem(innerValueType, innerValueSignature);
- return new DBusDictEntryItem(key, value);
- }
- case DBusType.Struct:
- {
- reader.AlignStruct();
- List items = new();
- SignatureReader innerSignatureReader = new(innerSignature);
- while (innerSignatureReader.TryRead(out DBusType innerDBusType, out ReadOnlySpan innerStructSignature))
- items.Add(reader.ReadDBusItem(innerDBusType, innerStructSignature));
- return new DBusStructItem(items);
- }
- case DBusType.Variant:
- return reader.ReadDBusVariant();
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
- }
-
- internal static class VariantWriter
- {
- public static void WriteDBusVariant(this ref MessageWriter writer, DBusVariantItem value)
- {
- writer.WriteSignature(Encoding.UTF8.GetBytes(value.Signature).AsSpan());
- writer.WriteDBusItem(value.Value);
- }
-
- public static void WriteDBusItem(this ref MessageWriter writer, DBusItem value)
- {
- switch (value)
- {
- case DBusVariantItem variantItem:
- writer.WriteDBusVariant(variantItem);
- break;
- case DBusByteItem byteItem:
- writer.WriteByte(byteItem.Value);
- break;
- case DBusBoolItem boolItem:
- writer.WriteBool(boolItem.Value);
- break;
- case DBusInt16Item int16Item:
- writer.WriteInt16(int16Item.Value);
- break;
- case DBusUInt16Item uInt16Item:
- writer.WriteUInt16(uInt16Item.Value);
- break;
- case DBusInt32Item int32Item:
- writer.WriteInt32(int32Item.Value);
- break;
- case DBusUInt32Item uInt32Item:
- writer.WriteUInt32(uInt32Item.Value);
- break;
- case DBusInt64Item int64Item:
- writer.WriteInt64(int64Item.Value);
- break;
- case DBusUInt64Item uInt64Item:
- writer.WriteUInt64(uInt64Item.Value);
- break;
- case DBusDoubleItem doubleItem:
- writer.WriteDouble(doubleItem.Value);
- break;
- case DBusStringItem stringItem:
- writer.WriteString(stringItem.Value);
- break;
- case DBusObjectPathItem objectPathItem:
- writer.WriteObjectPath(objectPathItem.Value);
- break;
- case DBusSignatureItem signatureItem:
- writer.WriteSignature(signatureItem.Value.ToString());
- break;
- case DBusArrayItem arrayItem:
- ArrayStart arrayStart = writer.WriteArrayStart(arrayItem.ArrayType);
- foreach (DBusItem item in arrayItem)
- writer.WriteDBusItem(item);
- writer.WriteArrayEnd(arrayStart);
- break;
- case DBusDictEntryItem dictEntryItem:
- writer.WriteStructureStart();
- writer.WriteDBusItem(dictEntryItem.Key);
- writer.WriteDBusItem(dictEntryItem.Value);
- break;
- case DBusStructItem structItem:
- writer.WriteStructureStart();
- foreach (DBusItem item in structItem)
- writer.WriteDBusItem(item);
- break;
- case DBusByteArrayItem byteArrayItem:
- ArrayStart byteArrayStart = writer.WriteArrayStart(DBusType.Byte);
- foreach (byte item in byteArrayItem)
- writer.WriteByte(item);
- writer.WriteArrayEnd(byteArrayStart);
- break;
- }
- }
- }
-
- internal abstract class DBusItem { }
-
- internal abstract class DBusBasicTypeItem : DBusItem { }
-
- internal class DBusVariantItem : DBusItem
- {
- public DBusVariantItem(string signature, DBusItem value)
- {
- Signature = signature;
- Value = value;
- }
-
- public string Signature { get; }
-
- public DBusItem Value { get; }
- }
-
- internal class DBusByteItem : DBusBasicTypeItem
- {
- public DBusByteItem(byte value)
- {
- Value = value;
- }
-
- public byte Value { get; }
- }
-
- internal class DBusBoolItem : DBusBasicTypeItem
- {
- public DBusBoolItem(bool value)
- {
- Value = value;
- }
-
- public bool Value { get; }
- }
-
- internal class DBusInt16Item : DBusBasicTypeItem
- {
- public DBusInt16Item(short value)
- {
- Value = value;
- }
-
- public short Value { get; }
- }
-
- internal class DBusUInt16Item : DBusBasicTypeItem
- {
- public DBusUInt16Item(ushort value)
- {
- Value = value;
- }
-
- public ushort Value { get; }
- }
-
- internal class DBusInt32Item : DBusBasicTypeItem
- {
- public DBusInt32Item(int value)
- {
- Value = value;
- }
-
- public int Value { get; }
- }
-
- internal class DBusUInt32Item : DBusBasicTypeItem
- {
- public DBusUInt32Item(uint value)
- {
- Value = value;
- }
-
- public uint Value { get; }
- }
-
- internal class DBusInt64Item : DBusBasicTypeItem
- {
- public DBusInt64Item(long value)
- {
- Value = value;
- }
-
- public long Value { get; }
- }
-
- internal class DBusUInt64Item : DBusBasicTypeItem
- {
- public DBusUInt64Item(ulong value)
- {
- Value = value;
- }
-
- public ulong Value { get; }
- }
-
- internal class DBusDoubleItem : DBusBasicTypeItem
- {
- public DBusDoubleItem(double value)
- {
- Value = value;
- }
-
- public double Value { get; }
- }
-
- internal class DBusStringItem : DBusBasicTypeItem
- {
- public DBusStringItem(string value)
- {
- Value = value;
- }
-
- public string Value { get; }
- }
-
- internal class DBusObjectPathItem : DBusBasicTypeItem
- {
- public DBusObjectPathItem(ObjectPath value)
- {
- Value = value;
- }
-
- public ObjectPath Value { get; }
- }
-
- internal class DBusSignatureItem : DBusBasicTypeItem
- {
- public DBusSignatureItem(Signature value)
- {
- Value = value;
- }
-
- public Signature Value { get; }
- }
-
- internal class DBusArrayItem : DBusItem, IReadOnlyList
- {
- private readonly IReadOnlyList _value;
-
- public DBusArrayItem(DBusType arrayType, IReadOnlyList value)
- {
- ArrayType = arrayType;
- _value = value;
- }
-
- public DBusType ArrayType { get; }
-
- public IEnumerator GetEnumerator() => _value.GetEnumerator();
-
- IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_value).GetEnumerator();
-
- public int Count => _value.Count;
-
- public DBusItem this[int index] => _value[index];
- }
-
- internal class DBusDictEntryItem : DBusItem
- {
- public DBusDictEntryItem(DBusBasicTypeItem key, DBusItem value)
- {
- Key = key;
- Value = value;
- }
-
- public DBusBasicTypeItem Key { get; }
-
- public DBusItem Value { get; }
- }
-
- internal class DBusStructItem : DBusItem, IReadOnlyList
- {
- private readonly IReadOnlyList _value;
-
- public DBusStructItem(IReadOnlyList value)
- {
- _value = value;
- }
-
- public IEnumerator GetEnumerator() => _value.GetEnumerator();
-
- IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_value).GetEnumerator();
-
- public int Count => _value.Count;
-
- public DBusItem this[int index] => _value[index];
- }
-
- internal class DBusByteArrayItem : DBusItem, IReadOnlyList
- {
- private readonly IReadOnlyList _value;
-
- public DBusByteArrayItem(IReadOnlyList value)
- {
- _value = value;
- }
-
- public IEnumerator GetEnumerator() => _value.GetEnumerator();
-
- IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_value).GetEnumerator();
-
- public int Count => _value.Count;
-
- public byte this[int index] => _value[index];
- }
-}
-""";
+ Parameter(
+ Identifier("writer"))
+ .WithType(
+ IdentifierName("MessageWriter"))
+ .AddModifiers(
+ Token(SyntaxKind.ThisKeyword),
+ Token(SyntaxKind.RefKeyword)),
+ Parameter(
+ Identifier("value"))
+ .WithType(
+ IdentifierName("ObjectPath")))
+ .WithExpressionBody(
+ ArrowExpressionClause(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", "WriteObjectPath"))
+ .AddArgumentListArguments(
+ Argument(
+ InvocationExpression(
+ MakeMemberAccessExpression("value", "ToString"))))))
+ .WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
+
+ private const string SignalHelperClass = """
+ using Tmds.DBus.Protocol;
+
+ //
+ #pragma warning disable
+ #nullable enable
+ namespace Tmds.DBus.SourceGenerator
+ {
+ internal static class SignalHelper
+ {
+ public static ValueTask WatchSignalAsync(Connection connection, MatchRule rule, Action handler, bool emitOnCapturedContext = true, ObserverFlags flags = ObserverFlags.None)
+ => connection.AddMatchAsync(rule, static (_, _) => null !, static (Exception? e, object _, object? _, object? handlerState) => ((Action)handlerState!).Invoke(e), null, handler, emitOnCapturedContext, flags);
+
+ public static ValueTask WatchSignalAsync(Connection connection, MatchRule rule, MessageValueReader reader, Action handler, bool emitOnCapturedContext = true, ObserverFlags flags = ObserverFlags.None)
+ => connection.AddMatchAsync(rule, reader, static (e, arg, _, handlerState) => ((Action)handlerState!).Invoke(e, arg), null, handler, emitOnCapturedContext, flags);
+
+ public static ValueTask WatchPropertiesChangedAsync(Connection connection, string destination, string path, string @interface, MessageValueReader> reader, Action> handler, bool emitOnCapturedContext = true, ObserverFlags flags = ObserverFlags.None)
+ {
+ MatchRule rule = new()
+ {
+ Type = MessageType.Signal,
+ Sender = destination,
+ Path = path,
+ Member = "PropertiesChanged",
+ Interface = "org.freedesktop.DBus.Properties",
+ Arg0 = @interface
+ };
+
+ return WatchSignalAsync(connection, rule, reader, handler, emitOnCapturedContext, flags);
+ }
+ }
+ }
+ """;
+
+ private const string PropertyChangesClass = """
+ //
+ #pragma warning disable
+ #nullable enable
+ namespace Tmds.DBus.SourceGenerator
+ {
+ internal record PropertyChanges(TProperties Properties, string[] Invalidated, string[] Changed)
+ {
+ public bool HasChanged(string property) => Array.IndexOf(Changed, property) != -1;
+ public bool IsInvalidated(string property) => Array.IndexOf(Invalidated, property) != -1;
+ }
+ }
+
+ """;
+
+ private const string DBusInterfaceHandlerInterface = """
+ using Tmds.DBus.Protocol;
+
+ //
+ #pragma warning disable
+ #nullable enable
+ namespace Tmds.DBus.SourceGenerator
+ {
+ internal interface IDBusInterfaceHandler
+ {
+ PathHandler? PathHandler { get; set; }
+
+ Connection Connection { get; }
+
+ string InterfaceName { get; }
+
+ ReadOnlyMemory IntrospectXml { get; }
+
+ void ReplyGetProperty(string name, MethodContext context);
+
+ void ReplyGetAllProperties(MethodContext context);
+
+ ValueTask ReplyInterfaceRequest(MethodContext context);
+ }
+ }
+
+ """;
+
+ private const string PathHandlerClass = """
+ using System.Collections;
+
+ using Tmds.DBus.Protocol;
+
+ //
+ #pragma warning disable
+ #nullable enable
+ namespace Tmds.DBus.SourceGenerator
+ {
+ internal class PathHandler : IMethodHandler
+ {
+ private readonly bool _runMethodHandlerSynchronously;
+ private readonly ICollection _dbusInterfaces;
+
+ public PathHandler(string path, bool runMethodHandlerSynchronously = true)
+ {
+ Path = path;
+ _runMethodHandlerSynchronously = runMethodHandlerSynchronously;
+ _dbusInterfaces = new List();
+ }
+
+ ///
+ public string Path { get; }
+
+ ///
+ public async ValueTask HandleMethodAsync(MethodContext context)
+ {
+ switch (context.Request.InterfaceAsString)
+ {
+ case "org.freedesktop.DBus.Properties":
+ switch (context.Request.MemberAsString, context.Request.SignatureAsString)
+ {
+ case ("Get", "ss"):
+ {
+ Reply();
+ void Reply()
+ {
+ Reader reader = context.Request.GetBodyReader();
+ string @interface = reader.ReadString();
+ IDBusInterfaceHandler? handler = _dbusInterfaces.FirstOrDefault(x => x.InterfaceName == @interface);
+ if (handler is null)
+ return;
+ string member = reader.ReadString();
+ handler.ReplyGetProperty(member, context);
+ }
+
+ break;
+ }
+ case ("GetAll", "s"):
+ {
+ Reply();
+ void Reply()
+ {
+ Reader reader = context.Request.GetBodyReader();
+ string @interface = reader.ReadString();
+ IDBusInterfaceHandler? handler = _dbusInterfaces.FirstOrDefault(x => x.InterfaceName == @interface);
+ if (handler is null)
+ return;
+ handler.ReplyGetAllProperties(context);
+ }
+
+ break;
+ }
+ }
+
+ break;
+ case "org.freedesktop.DBus.Introspectable":
+ context.ReplyIntrospectXml(_dbusInterfaces.Select(static x => x.IntrospectXml).ToArray());
+ break;
+ }
+
+ IDBusInterfaceHandler? handler = _dbusInterfaces.FirstOrDefault(x => x.InterfaceName == context.Request.InterfaceAsString);
+ if (handler is not null)
+ await handler.ReplyInterfaceRequest(context);
+ }
+
+ ///
+ public bool RunMethodHandlerSynchronously(Message message) => _runMethodHandlerSynchronously;
+
+ ///
+ public void Add(IDBusInterfaceHandler item)
+ {
+ item.PathHandler = this;
+ _dbusInterfaces.Add(item);
+ }
+
+ ///
+ public bool Contains(IDBusInterfaceHandler item) => _dbusInterfaces.Contains(item);
+
+ ///
+ public bool Remove(IDBusInterfaceHandler item)
+ {
+ item.PathHandler = null;
+ return _dbusInterfaces.Remove(item);
+ }
+
+ ///
+ public int Count => _dbusInterfaces.Count;
+ }
+ }
+ """;
}
}
diff --git a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Handler.cs b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Handler.cs
index a49357685b..64572b32f3 100644
--- a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Handler.cs
+++ b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Handler.cs
@@ -1,4 +1,3 @@
-using System;
using System.IO;
using System.Linq;
using System.Xml;
@@ -18,20 +17,27 @@ namespace Tmds.DBus.SourceGenerator
private ClassDeclarationSyntax GenerateHandler(DBusInterface dBusInterface)
{
ClassDeclarationSyntax cl = ClassDeclaration(Pascalize(dBusInterface.Name!))
- .AddModifiers(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.AbstractKeyword))
+ .AddModifiers(
+ Token(SyntaxKind.InternalKeyword),
+ Token(SyntaxKind.AbstractKeyword))
.AddBaseListTypes(
- SimpleBaseType(ParseTypeName("IMethodHandler")))
+ SimpleBaseType(
+ IdentifierName("IDBusInterfaceHandler")))
.AddMembers(
- FieldDeclaration(
- VariableDeclaration(NullableType(ParseTypeName("SynchronizationContext")))
- .AddVariables(
- VariableDeclarator("_synchronizationContext")))
- .AddModifiers(Token(SyntaxKind.PrivateKeyword)),
- ConstructorDeclaration(Pascalize(dBusInterface.Name!))
- .AddModifiers(Token(SyntaxKind.PublicKeyword))
+ MakePrivateReadOnlyField(
+ "_synchronizationContext",
+ NullableType(
+ IdentifierName("SynchronizationContext"))),
+ ConstructorDeclaration(
+ Pascalize(dBusInterface.Name!))
+ .AddModifiers(
+ Token(SyntaxKind.PublicKeyword))
.AddParameterListParameters(
- Parameter(Identifier("emitOnCapturedContext"))
- .WithType(PredefinedType(Token(SyntaxKind.BoolKeyword)))
+ Parameter(
+ Identifier("emitOnCapturedContext"))
+ .WithType(
+ PredefinedType(
+ Token(SyntaxKind.BoolKeyword)))
.WithDefault(
EqualsValueClause(
LiteralExpression(SyntaxKind.TrueLiteralExpression))))
@@ -40,51 +46,39 @@ namespace Tmds.DBus.SourceGenerator
IfStatement(
IdentifierName("emitOnCapturedContext"),
ExpressionStatement(
- AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName("_synchronizationContext"),
+ AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
+ IdentifierName("_synchronizationContext"),
MakeMemberAccessExpression("SynchronizationContext", "Current")))))),
- MakeGetOnlyProperty(ParseTypeName("Connection"), "Connection", Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.AbstractKeyword)),
- MakeGetOnlyProperty(PredefinedType(Token(SyntaxKind.StringKeyword)), "Path", Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.AbstractKeyword)));
-
- MethodDeclarationSyntax handleMethod = MethodDeclaration(ParseTypeName("ValueTask"), "HandleMethodAsync")
- .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.AsyncKeyword))
- .AddParameterListParameters(
- Parameter(Identifier("context"))
- .WithType(ParseTypeName("MethodContext")));
-
- SwitchStatementSyntax switchStatement = SwitchStatement(MakeMemberAccessExpression("context", "Request", "InterfaceAsString"));
-
- AddHandlerMethods(ref cl, ref switchStatement, dBusInterface);
- AddHandlerSignals(ref cl, dBusInterface);
- AddHandlerProperties(ref cl, ref switchStatement, dBusInterface);
- AddHandlerIntrospect(ref cl, ref switchStatement, dBusInterface);
-
- if (dBusInterface.Properties?.Length > 0)
- {
- cl = cl.AddMembers(
- MakeGetOnlyProperty(ParseTypeName("Properties"), "BackingProperties", Token(SyntaxKind.PublicKeyword))
+ MakeGetSetProperty(
+ NullableType(
+ IdentifierName("PathHandler")),
+ "PathHandler",
+ Token(SyntaxKind.PublicKeyword)),
+ MakeGetOnlyProperty(
+ IdentifierName("Connection"),
+ "Connection",
+ Token(SyntaxKind.PublicKeyword),
+ Token(SyntaxKind.AbstractKeyword)),
+ MakeGetOnlyProperty(
+ PredefinedType(
+ Token(SyntaxKind.StringKeyword)),
+ "InterfaceName",
+ Token(SyntaxKind.PublicKeyword))
.WithInitializer(
EqualsValueClause(
- InvocationExpression(
- ObjectCreationExpression(ParseTypeName("Properties")))))
- .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
- }
+ MakeLiteralExpression(dBusInterface.Name!)))
+ .WithSemicolonToken(
+ Token(SyntaxKind.SemicolonToken)));
- cl = cl.AddMembers(
- MethodDeclaration(PredefinedType(Token(SyntaxKind.BoolKeyword)), "RunMethodHandlerSynchronously")
- .AddModifiers(Token(SyntaxKind.PublicKeyword))
- .AddParameterListParameters(
- Parameter(Identifier("message")).WithType(ParseTypeName("Message")))
- .WithExpressionBody(
- ArrowExpressionClause(
- LiteralExpression(SyntaxKind.TrueLiteralExpression)))
- .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
- handleMethod.WithBody(
- Block(switchStatement)));
+ AddHandlerProperties(ref cl, dBusInterface);
+ AddHandlerIntrospect(ref cl, dBusInterface);
+ AddHandlerMethods(ref cl, dBusInterface);
+ AddHandlerSignals(ref cl, dBusInterface);
return cl;
}
- private void AddHandlerMethods(ref ClassDeclarationSyntax cl, ref SwitchStatementSyntax sw, DBusInterface dBusInterface)
+ private void AddHandlerMethods(ref ClassDeclarationSyntax cl, DBusInterface dBusInterface)
{
if (dBusInterface.Methods is null)
return;
@@ -96,43 +90,38 @@ namespace Tmds.DBus.SourceGenerator
DBusArgument[]? inArgs = dBusMethod.Arguments?.Where(static m => m.Direction is null or "in").ToArray();
DBusArgument[]? outArgs = dBusMethod.Arguments?.Where(static m => m.Direction == "out").ToArray();
- SwitchSectionSyntax switchSection = SwitchSection();
-
- if (inArgs?.Length > 0)
- {
- switchSection = switchSection.AddLabels(
- CaseSwitchLabel(
- TupleExpression()
- .AddArguments(
- Argument(MakeLiteralExpression(dBusMethod.Name!)),
- Argument(MakeLiteralExpression(ParseSignature(inArgs)!)))));
- }
- else
- {
- switchSection = switchSection.AddLabels(
+ SwitchSectionSyntax switchSection = SwitchSection()
+ .AddLabels(
CasePatternSwitchLabel(
RecursivePattern()
.WithPositionalPatternClause(
PositionalPatternClause()
.AddSubpatterns(
Subpattern(
- ConstantPattern(MakeLiteralExpression("Introspect"))),
+ ConstantPattern(
+ MakeLiteralExpression(dBusMethod.Name!))),
Subpattern(
- BinaryPattern(SyntaxKind.OrPattern, ConstantPattern(MakeLiteralExpression(string.Empty)),
- ConstantPattern(LiteralExpression(SyntaxKind.NullLiteralExpression)))))),
+ inArgs?.Length > 0
+ ? ConstantPattern(
+ MakeLiteralExpression(
+ ParseSignature(inArgs)!))
+ : BinaryPattern(SyntaxKind.OrPattern,
+ ConstantPattern(
+ MakeLiteralExpression(string.Empty)),
+ ConstantPattern(
+ LiteralExpression(SyntaxKind.NullLiteralExpression)))))),
Token(SyntaxKind.ColonToken)));
- }
BlockSyntax switchSectionBlock = Block();
string abstractMethodName = $"On{Pascalize(dBusMethod.Name!)}Async";
- MethodDeclarationSyntax abstractMethod = outArgs?.Length > 0
- ? MethodDeclaration(ParseTypeName($"ValueTask<{ParseReturnType(outArgs)!}>"), abstractMethodName)
- : MethodDeclaration(ParseTypeName("ValueTask"), abstractMethodName);
+ MethodDeclarationSyntax abstractMethod = MethodDeclaration(
+ ParseValueTaskReturnType(outArgs, AccessMode.Write), abstractMethodName);
if (inArgs?.Length > 0)
- abstractMethod = abstractMethod.WithParameterList(ParseParameterList(inArgs));
+ abstractMethod = abstractMethod.WithParameterList(
+ ParseParameterList(inArgs, AccessMode.Read));
abstractMethod = abstractMethod
.AddModifiers(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.AbstractKeyword))
@@ -144,30 +133,29 @@ namespace Tmds.DBus.SourceGenerator
{
BlockSyntax readParametersMethodBlock = Block(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("Reader"))
+ VariableDeclaration(IdentifierName("Reader"))
.AddVariables(
VariableDeclarator("reader")
.WithInitializer(
EqualsValueClause(
InvocationExpression(MakeMemberAccessExpression("context", "Request", "GetBodyReader")))))));
- SyntaxList argFields = List();
+ StatementSyntax[] argFields = new StatementSyntax[inArgs.Length];
for (int i = 0; i < inArgs.Length; i++)
{
- string identifier = inArgs[i].Name is not null ? SanitizeIdentifier(inArgs[i].Name!) : $"arg{i}";
+ string identifier = inArgs[i].Name is not null ? SanitizeIdentifier(Camelize(inArgs[i].Name!)) : $"arg{i}";
readParametersMethodBlock = readParametersMethodBlock.AddStatements(
ExpressionStatement(
AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(identifier), InvocationExpression(
MakeMemberAccessExpression("reader", GetOrAddReadMethod(inArgs[i]))))));
- argFields = argFields.Add(
- LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName(inArgs[i].DotNetType))
- .AddVariables(
- VariableDeclarator(identifier))));
+ argFields[i] = LocalDeclarationStatement(
+ VariableDeclaration(GetDotnetType(inArgs[i], AccessMode.Read))
+ .AddVariables(
+ VariableDeclarator(identifier)));
}
- switchSectionBlock = switchSectionBlock.AddStatements(argFields.ToArray());
+ switchSectionBlock = switchSectionBlock.AddStatements(argFields);
switchSectionBlock = switchSectionBlock.AddStatements(
ExpressionStatement(
InvocationExpression(
@@ -175,122 +163,36 @@ namespace Tmds.DBus.SourceGenerator
LocalFunctionStatement(
PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("ReadParameters"))
.WithBody(readParametersMethodBlock));
-
- if (outArgs is null || outArgs.Length == 0)
- {
- switchSectionBlock = switchSectionBlock.AddStatements(
- IfStatement(
- IsPatternExpression(
- IdentifierName("_synchronizationContext"), UnaryPattern(ConstantPattern(LiteralExpression(SyntaxKind.NullLiteralExpression)))),
- Block(
- LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("TaskCompletionSource"))
- .AddVariables(
- VariableDeclarator("tsc")
- .WithInitializer(
- EqualsValueClause(
- ImplicitObjectCreationExpression())))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("_synchronizationContext", "Post"))
- .AddArgumentListArguments(
- Argument(
- SimpleLambdaExpression(
- Parameter(
- Identifier("_")))
- .WithAsyncKeyword(Token(SyntaxKind.AsyncKeyword))
- .WithBlock(
- Block(
- TryStatement()
- .AddBlockStatements(
- ExpressionStatement(
- AwaitExpression(
- InvocationExpression(
- IdentifierName(abstractMethodName))
- .AddArgumentListArguments(
- inArgs.Select(static (x, i) =>
- Argument(
- IdentifierName(x.Name is not null ? SanitizeIdentifier(x.Name) : $"arg{i}"))).ToArray()))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("tsc", "SetResult"))
- .AddArgumentListArguments(
- Argument(
- LiteralExpression(SyntaxKind.TrueLiteralExpression)))))
- .AddCatches(
- CatchClause()
- .WithDeclaration(CatchDeclaration(ParseTypeName("Exception"))
- .WithIdentifier(Identifier("e")))
- .AddBlockStatements(
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("tsc", "SetException"))
- .AddArgumentListArguments(
- Argument(IdentifierName("e"))))))))),
- Argument(
- LiteralExpression(SyntaxKind.NullLiteralExpression)))),
- ExpressionStatement(
- AwaitExpression(
- MakeMemberAccessExpression("tsc", "Task")))),
- ElseClause(
- Block(
- ExpressionStatement(
- AwaitExpression(
- InvocationExpression(
- IdentifierName(abstractMethodName))
- .AddArgumentListArguments(
- inArgs.Select(static (x, i) =>
- Argument(
- IdentifierName(x.Name is not null ? SanitizeIdentifier(x.Name) : $"arg{i}"))).ToArray())))))));
-
- BlockSyntax replyMethodBlock = Block(
- LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("MessageWriter"))
- .AddVariables(
- VariableDeclarator("writer")
- .WithInitializer(
- EqualsValueClause(
- InvocationExpression(
- MakeMemberAccessExpression("context", "CreateReplyWriter"))
- .AddArgumentListArguments(
- Argument(
- PostfixUnaryExpression(SyntaxKind.SuppressNullableWarningExpression, LiteralExpression(SyntaxKind.NullLiteralExpression)))))))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("context", "Reply"))
- .AddArgumentListArguments(
- Argument(
- InvocationExpression(
- MakeMemberAccessExpression("writer", "CreateMessage"))))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("writer", "Dispose"))));
-
- switchSectionBlock = switchSectionBlock.AddStatements(
- IfStatement(
- PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, MakeMemberAccessExpression("context", "NoReplyExpected")),
- ExpressionStatement(
- InvocationExpression(
- IdentifierName("Reply")))),
- LocalFunctionStatement(
- PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("Reply"))
- .WithBody(replyMethodBlock));
- }
}
if (outArgs?.Length > 0)
{
switchSectionBlock = switchSectionBlock.AddStatements(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName(ParseReturnType(outArgs)!))
+ VariableDeclaration(ParseReturnType(outArgs, AccessMode.Write)!)
.AddVariables(
- VariableDeclarator("ret"))),
+ VariableDeclarator("ret"))));
+ }
+
+ ExpressionSyntax callAbstractMethod = AwaitExpression(
+ InvocationExpression(
+ IdentifierName(abstractMethodName))
+ .AddArgumentListArguments(
+ inArgs?.Select(static (argument, i) =>
+ Argument(
+ IdentifierName(argument.Name is not null
+ ? SanitizeIdentifier(Camelize(argument.Name))
+ : $"arg{i}")))
+ .ToArray() ?? []));
+
+ switchSectionBlock = switchSectionBlock.AddStatements(
IfStatement(
IsPatternExpression(
IdentifierName("_synchronizationContext"), UnaryPattern(ConstantPattern(LiteralExpression(SyntaxKind.NullLiteralExpression)))),
Block(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName($"TaskCompletionSource<{ParseReturnType(outArgs)!}>"))
+ VariableDeclaration(
+ ParseTaskCompletionSourceType(outArgs, AccessMode.Write))
.AddVariables(
VariableDeclarator("tsc")
.WithInitializer(
@@ -309,28 +211,27 @@ namespace Tmds.DBus.SourceGenerator
Block(
TryStatement()
.AddBlockStatements(
- LocalDeclarationStatement(
+ outArgs?.Length > 0
+ ? LocalDeclarationStatement(
VariableDeclaration(
- ParseTypeName(ParseReturnType(outArgs)!))
+ ParseReturnType(outArgs, AccessMode.Write)!)
.AddVariables(
VariableDeclarator("ret1")
.WithInitializer(
- EqualsValueClause(
- AwaitExpression(
- InvocationExpression(
- IdentifierName(abstractMethodName))
- .AddArgumentListArguments(
- inArgs?.Select(static (x, i) =>
- Argument(
- IdentifierName(x.Name is not null ? SanitizeIdentifier(x.Name) : $"arg{i}"))).ToArray() ?? Array.Empty())))))),
+ EqualsValueClause(callAbstractMethod))))
+ : ExpressionStatement(callAbstractMethod),
ExpressionStatement(
InvocationExpression(
MakeMemberAccessExpression("tsc", "SetResult"))
.AddArgumentListArguments(
- Argument(IdentifierName("ret1")))))
+ Argument(
+ outArgs?.Length > 0
+ ? IdentifierName("ret1")
+ : LiteralExpression(SyntaxKind.TrueLiteralExpression)))))
.AddCatches(
CatchClause()
- .WithDeclaration(CatchDeclaration(ParseTypeName("Exception"))
+ .WithDeclaration(
+ CatchDeclaration(IdentifierName("Exception"))
.WithIdentifier(Identifier("e")))
.WithBlock(
Block(
@@ -342,22 +243,23 @@ namespace Tmds.DBus.SourceGenerator
Argument(
LiteralExpression(SyntaxKind.NullLiteralExpression)))),
ExpressionStatement(
- MakeAssignmentExpression(IdentifierName("ret"), AwaitExpression(
- MakeMemberAccessExpression("tsc", "Task"))))),
+ outArgs?.Length > 0
+ ? MakeAssignmentExpression(
+ IdentifierName("ret"), AwaitExpression(
+ MakeMemberAccessExpression("tsc", "Task")))
+ : AwaitExpression(
+ MakeMemberAccessExpression("tsc", "Task")))),
ElseClause(
Block(
ExpressionStatement(
- MakeAssignmentExpression(IdentifierName("ret"), AwaitExpression(
- InvocationExpression(
- IdentifierName(abstractMethodName))
- .AddArgumentListArguments(
- inArgs?.Select(static (x, i) =>
- Argument(
- IdentifierName(x.Name is not null ? SanitizeIdentifier(x.Name) : $"arg{i}"))).ToArray() ?? Array.Empty()))))))));
+ outArgs?.Length > 0
+ ? MakeAssignmentExpression(
+ IdentifierName("ret"), callAbstractMethod)
+ : callAbstractMethod)))));
BlockSyntax replyMethodBlock = Block(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("MessageWriter"))
+ VariableDeclaration(IdentifierName("MessageWriter"))
.AddVariables(
VariableDeclarator("writer")
.WithInitializer(
@@ -365,9 +267,13 @@ namespace Tmds.DBus.SourceGenerator
InvocationExpression(
MakeMemberAccessExpression("context", "CreateReplyWriter"))
.AddArgumentListArguments(
- Argument(MakeLiteralExpression(ParseSignature(outArgs)!))))))));
+ Argument(
+ outArgs?.Length > 0
+ ? MakeLiteralExpression(
+ ParseSignature(outArgs)!)
+ : LiteralExpression(SyntaxKind.NullLiteralExpression))))))));
- if (outArgs.Length == 1)
+ if (outArgs?.Length == 1)
{
replyMethodBlock = replyMethodBlock.AddStatements(
ExpressionStatement(
@@ -377,7 +283,7 @@ namespace Tmds.DBus.SourceGenerator
Argument(
IdentifierName("ret")))));
}
- else
+ else if (outArgs?.Length > 1)
{
for (int i = 0; i < outArgs.Length; i++)
{
@@ -387,7 +293,9 @@ namespace Tmds.DBus.SourceGenerator
MakeMemberAccessExpression("writer", GetOrAddWriteMethod(outArgs[i])))
.AddArgumentListArguments(
Argument(
- MakeMemberAccessExpression("ret", outArgs[i].Name is not null ? SanitizeIdentifier(outArgs[i].Name!) : $"Item{i + 1}")))));
+ MakeMemberAccessExpression("ret", outArgs[i].Name is not null
+ ? SanitizeIdentifier(Pascalize(outArgs[i].Name!))
+ : $"Item{i + 1}")))));
}
}
@@ -404,192 +312,198 @@ namespace Tmds.DBus.SourceGenerator
MakeMemberAccessExpression("writer", "Dispose"))));
switchSectionBlock = switchSectionBlock.AddStatements(
- ExpressionStatement(
- InvocationExpression(
- IdentifierName("Reply"))),
+ IfStatement(
+ PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, MakeMemberAccessExpression("context", "NoReplyExpected")),
+ ExpressionStatement(
+ InvocationExpression(
+ IdentifierName("Reply")))),
LocalFunctionStatement(
PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("Reply"))
.WithBody(replyMethodBlock));
- }
- switchSectionBlock = switchSectionBlock.AddStatements(BreakStatement());
-
- switchSections = switchSections.Add(switchSection.AddStatements(switchSectionBlock));
+ switchSections = switchSections.Add(
+ switchSection.AddStatements(
+ switchSectionBlock.AddStatements(
+ BreakStatement())));
}
- sw = sw.AddSections(
- SwitchSection()
- .AddLabels(
- CaseSwitchLabel(MakeLiteralExpression(dBusInterface.Name!)))
- .AddStatements(
- SwitchStatement(
- TupleExpression()
- .AddArguments(
- Argument(MakeMemberAccessExpression("context", "Request", "MemberAsString")),
- Argument(MakeMemberAccessExpression("context", "Request", "SignatureAsString"))))
- .WithSections(switchSections),
- BreakStatement()));
+ cl = cl.AddMembers(
+ MethodDeclaration(
+ IdentifierName("ValueTask"),
+ "ReplyInterfaceRequest")
+ .AddModifiers(
+ Token(SyntaxKind.PublicKeyword),
+ Token(SyntaxKind.AsyncKeyword))
+ .AddParameterListParameters(
+ Parameter(
+ Identifier("context"))
+ .WithType(
+ IdentifierName("MethodContext")))
+ .WithBody(
+ Block(
+ SwitchStatement(
+ TupleExpression()
+ .AddArguments(
+ Argument(
+ MakeMemberAccessExpression("context", "Request", "MemberAsString")),
+ Argument(
+ MakeMemberAccessExpression("context", "Request", "SignatureAsString"))))
+ .WithSections(switchSections))));
}
- private void AddHandlerProperties(ref ClassDeclarationSyntax cl, ref SwitchStatementSyntax sw, DBusInterface dBusInterface)
+ private void AddHandlerProperties(ref ClassDeclarationSyntax cl, DBusInterface dBusInterface)
{
- if (dBusInterface.Properties is null)
- return;
+ dBusInterface.Properties ??= [];
- sw = sw.AddSections(
- SwitchSection()
- .AddLabels(
- CaseSwitchLabel(MakeLiteralExpression("org.freedesktop.DBus.Properties")))
- .AddStatements(
- SwitchStatement(
- TupleExpression()
- .AddArguments(
- Argument(MakeMemberAccessExpression("context", "Request", "MemberAsString")),
- Argument(MakeMemberAccessExpression("context", "Request", "SignatureAsString"))))
- .AddSections(
- SwitchSection()
- .AddLabels(
- CaseSwitchLabel(
- TupleExpression()
- .AddArguments(
- Argument(MakeLiteralExpression("Get")),
- Argument(MakeLiteralExpression("ss")))))
- .AddStatements(
- Block(
+ cl = dBusInterface.Properties!.Aggregate(cl, static (current, property) =>
+ current.AddMembers(
+ MakeGetSetProperty(
+ GetDotnetType(property, AccessMode.Write, true),
+ Pascalize(property.Name!), Token(SyntaxKind.PublicKeyword))));
+
+ cl = cl.AddMembers(
+ MethodDeclaration(
+ PredefinedType(
+ Token(SyntaxKind.VoidKeyword)),
+ "ReplyGetProperty")
+ .AddModifiers(
+ Token(SyntaxKind.PublicKeyword))
+ .AddParameterListParameters(
+ Parameter(
+ Identifier("name"))
+ .WithType(
+ PredefinedType(
+ Token(SyntaxKind.StringKeyword))),
+ Parameter(
+ Identifier("context"))
+ .WithType(
+ IdentifierName("MethodContext")))
+ .WithBody(
+ Block(
+ SwitchStatement(
+ IdentifierName("name"))
+ .WithSections(
+ List(
+ dBusInterface.Properties.Select(property =>
+ SwitchSection()
+ .AddLabels(
+ CaseSwitchLabel(
+ MakeLiteralExpression(property.Name!)))
+ .AddStatements(
+ Block(
+ LocalDeclarationStatement(
+ VariableDeclaration(IdentifierName("MessageWriter"))
+ .AddVariables(
+ VariableDeclarator("writer")
+ .WithInitializer(
+ EqualsValueClause(
+ InvocationExpression(
+ MakeMemberAccessExpression("context", "CreateReplyWriter"))
+ .AddArgumentListArguments(
+ Argument(
+ MakeLiteralExpression("v"))))))),
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", "WriteSignature"))
+ .AddArgumentListArguments(
+ Argument(
+ MakeLiteralExpression(property.Type!)))),
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", GetOrAddWriteMethod(property)))
+ .AddArgumentListArguments(
+ Argument(
+ IdentifierName(
+ Pascalize(property.Name!))))),
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("context", "Reply"))
+ .AddArgumentListArguments(
+ Argument(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", "CreateMessage"))))),
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", "Dispose"))),
+ BreakStatement()))))))),
+ MethodDeclaration(
+ PredefinedType(
+ Token(SyntaxKind.VoidKeyword)),
+ "ReplyGetAllProperties")
+ .AddModifiers(
+ Token(SyntaxKind.PublicKeyword))
+ .AddParameterListParameters(
+ Parameter(
+ Identifier("context"))
+ .WithType(
+ IdentifierName("MethodContext")))
+ .WithBody(
+ Block(
+ ExpressionStatement(
+ InvocationExpression(IdentifierName("Reply"))),
+ LocalFunctionStatement(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("Reply"))
+ .AddBodyStatements(
+ LocalDeclarationStatement(
+ VariableDeclaration(IdentifierName("MessageWriter"))
+ .AddVariables(
+ VariableDeclarator("writer")
+ .WithInitializer(
+ EqualsValueClause(
+ InvocationExpression(
+ MakeMemberAccessExpression("context", "CreateReplyWriter"))
+ .AddArgumentListArguments(
+ Argument(MakeLiteralExpression("a{sv}"))))))),
+ LocalDeclarationStatement(
+ VariableDeclaration(IdentifierName("ArrayStart"))
+ .AddVariables(
+ VariableDeclarator("dictStart")
+ .WithInitializer(
+ EqualsValueClause(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", "WriteDictionaryStart")))))))
+ .AddBodyStatements(
+ dBusInterface.Properties.SelectMany(property =>
+ new StatementSyntax[]
+ {
ExpressionStatement(
- InvocationExpression(IdentifierName("Reply"))),
- LocalFunctionStatement(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("Reply"))
- .AddBodyStatements(
- LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("Reader"))
- .AddVariables(
- VariableDeclarator("reader")
- .WithInitializer(
- EqualsValueClause(
- InvocationExpression(
- MakeMemberAccessExpression("context", "Request",
- "GetBodyReader")))))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("reader", "ReadString"))),
- LocalDeclarationStatement(
- VariableDeclaration(PredefinedType(Token(SyntaxKind.StringKeyword)))
- .AddVariables(
- VariableDeclarator("member")
- .WithInitializer(
- EqualsValueClause(
- InvocationExpression(
- MakeMemberAccessExpression("reader", "ReadString")))))),
- SwitchStatement(IdentifierName("member"))
- .WithSections(
- List(
- dBusInterface.Properties.Select(static dBusProperty =>
- SwitchSection()
- .AddLabels(
- CaseSwitchLabel(
- MakeLiteralExpression(dBusProperty.Name!)))
- .AddStatements(
- Block(
- LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("MessageWriter"))
- .AddVariables(
- VariableDeclarator("writer")
- .WithInitializer(
- EqualsValueClause(
- InvocationExpression(
- MakeMemberAccessExpression("context", "CreateReplyWriter"))
- .AddArgumentListArguments(
- Argument(
- MakeLiteralExpression("v"))))))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("writer", "WriteDBusVariant"))
- .AddArgumentListArguments(
- Argument(
- InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusVariantItem")))
- .AddArgumentListArguments(
- Argument(
- MakeLiteralExpression(ParseSignature(new[] { dBusProperty })!)),
- Argument(
- MakeGetDBusVariantExpression(dBusProperty,
- MakeMemberAccessExpression("BackingProperties", dBusProperty.Name!))))))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("context", "Reply"))
- .AddArgumentListArguments(
- Argument(
- InvocationExpression(
- MakeMemberAccessExpression("writer", "CreateMessage"))))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("writer", "Dispose"))),
- BreakStatement())))))),
- BreakStatement())),
- SwitchSection()
- .AddLabels(
- CaseSwitchLabel(
- TupleExpression()
- .AddArguments(
- Argument(MakeLiteralExpression("GetAll")),
- Argument(MakeLiteralExpression("s")))))
- .AddStatements(
- Block(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", "WriteDictionaryEntryStart"))),
ExpressionStatement(
- InvocationExpression(IdentifierName("Reply"))),
- LocalFunctionStatement(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("Reply"))
- .AddBodyStatements(
- LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("MessageWriter"))
- .AddVariables(
- VariableDeclarator("writer")
- .WithInitializer(
- EqualsValueClause(
- InvocationExpression(
- MakeMemberAccessExpression("context", "CreateReplyWriter"))
- .AddArgumentListArguments(
- Argument(MakeLiteralExpression("a{sv}"))))))),
- LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("Dictionary"))
- .AddVariables(
- VariableDeclarator("dict")
- .WithInitializer(
- EqualsValueClause(
- ObjectCreationExpression(ParseTypeName("Dictionary"))
- .WithInitializer(
- InitializerExpression(SyntaxKind.CollectionInitializerExpression)
- .WithExpressions(
- SeparatedList(
- dBusInterface.Properties.Select(static dBusProperty =>
- InitializerExpression(SyntaxKind.ComplexElementInitializerExpression)
- .AddExpressions(
- MakeLiteralExpression(dBusProperty.Name!), InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusVariantItem")))
- .AddArgumentListArguments(
- Argument(
- MakeLiteralExpression(ParseSignature(new [] { dBusProperty })!)),
- Argument(
- MakeGetDBusVariantExpression(dBusProperty, MakeMemberAccessExpression("BackingProperties", dBusProperty.Name!))))))))))))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("writer", GetOrAddWriteMethod(new DBusValue { Type = "a{sv}" })))
- .AddArgumentListArguments(
- Argument(IdentifierName("dict")))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("context", "Reply"))
- .AddArgumentListArguments(
- Argument(
- InvocationExpression(MakeMemberAccessExpression("writer", "CreateMessage")))))),
- BreakStatement()))),
- BreakStatement()));
-
- AddPropertiesClass(ref cl, dBusInterface);
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", "WriteString"))
+ .AddArgumentListArguments(
+ Argument(
+ MakeLiteralExpression(property.Name!)))),
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", "WriteSignature"))
+ .AddArgumentListArguments(
+ Argument(
+ MakeLiteralExpression(property.Type!)))),
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", GetOrAddWriteMethod(property)))
+ .AddArgumentListArguments(
+ Argument(
+ IdentifierName(
+ Pascalize(property.Name!)))))
+ }).ToArray())
+ .AddBodyStatements(
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", "WriteDictionaryEnd"))
+ .AddArgumentListArguments(
+ Argument(
+ IdentifierName("dictStart")))),
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("context", "Reply"))
+ .AddArgumentListArguments(
+ Argument(
+ InvocationExpression(MakeMemberAccessExpression("writer", "CreateMessage")))))))));
}
- private void AddHandlerIntrospect(ref ClassDeclarationSyntax cl, ref SwitchStatementSyntax sw, DBusInterface dBusInterface)
+ private void AddHandlerIntrospect(ref ClassDeclarationSyntax cl, DBusInterface dBusInterface)
{
XmlSerializer xmlSerializer = new(typeof(DBusInterface));
using StringWriter stringWriter = new();
@@ -598,75 +512,52 @@ namespace Tmds.DBus.SourceGenerator
string introspect = stringWriter.ToString();
cl = cl.AddMembers(
- FieldDeclaration(
- VariableDeclaration(ParseTypeName("ReadOnlyMemory"))
- .AddVariables(
- VariableDeclarator("_introspectXml")
- .WithInitializer(
- EqualsValueClause(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, LiteralExpression(SyntaxKind.Utf8StringLiteralExpression, Utf8Literal(introspect)), IdentifierName("ToArray")))))))
- .AddModifiers(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword)));
-
- sw = sw.AddSections(
- SwitchSection()
- .AddLabels(
- CaseSwitchLabel(MakeLiteralExpression("org.freedesktop.DBus.Introspectable")))
- .AddStatements(
- SwitchStatement(
- TupleExpression()
- .AddArguments(
- Argument(MakeMemberAccessExpression("context", "Request", "MemberAsString")),
- Argument(MakeMemberAccessExpression("context", "Request", "SignatureAsString"))))
- .AddSections(
- SwitchSection()
- .AddLabels(
- CasePatternSwitchLabel(
- RecursivePattern()
- .WithPositionalPatternClause(
- PositionalPatternClause()
- .AddSubpatterns(
- Subpattern(
- ConstantPattern(MakeLiteralExpression("Introspect"))),
- Subpattern(
- BinaryPattern(SyntaxKind.OrPattern, ConstantPattern(MakeLiteralExpression(string.Empty)), ConstantPattern(LiteralExpression(SyntaxKind.NullLiteralExpression)))))),
- Token(SyntaxKind.ColonToken)))
- .AddStatements(
- Block(
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("context", "ReplyIntrospectXml"))
- .AddArgumentListArguments(
- Argument(
- ImplicitArrayCreationExpression(
- InitializerExpression(SyntaxKind.ArrayInitializerExpression)
- .AddExpressions(IdentifierName("_introspectXml")))))),
- BreakStatement()))),
- BreakStatement()));
+ MakeGetOnlyProperty(
+ GenericName("ReadOnlyMemory")
+ .AddTypeArgumentListArguments(
+ PredefinedType(
+ Token(SyntaxKind.ByteKeyword))),
+ "IntrospectXml",
+ Token(SyntaxKind.PublicKeyword))
+ .WithInitializer(
+ EqualsValueClause(
+ InvocationExpression(
+ MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, LiteralExpression(SyntaxKind.Utf8StringLiteralExpression, Utf8Literal(introspect)), IdentifierName("ToArray")))))
+ .WithSemicolonToken(
+ Token(SyntaxKind.SemicolonToken)));
}
private void AddHandlerSignals(ref ClassDeclarationSyntax cl, DBusInterface dBusInterface)
{
if (dBusInterface.Signals is null)
return;
- foreach (DBusSignal dBusSignal in dBusInterface.Signals)
- {
- MethodDeclarationSyntax method = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), $"Emit{Pascalize(dBusSignal.Name!)}")
- .AddModifiers(Token(SyntaxKind.ProtectedKeyword));
- if (dBusSignal.Arguments?.Length > 0)
+ foreach (DBusSignal signal in dBusInterface.Signals)
+ {
+ MethodDeclarationSyntax method = MethodDeclaration(
+ PredefinedType(
+ Token(SyntaxKind.VoidKeyword)),
+ $"Emit{Pascalize(signal.Name!)}")
+ .AddModifiers(
+ Token(SyntaxKind.ProtectedKeyword));
+
+ if (signal.Arguments?.Length > 0)
{
method = method.WithParameterList(
ParameterList(
SeparatedList(
- dBusSignal.Arguments.Select(
- static (x, i) => Parameter(Identifier(x.Name is not null ? SanitizeIdentifier(x.Name) : $"arg{i}")).WithType(ParseTypeName(x.DotNetType))))));
+ signal.Arguments.Select(
+ static (argument, i) => Parameter(
+ Identifier(argument.Name is not null ? SanitizeIdentifier(Camelize(argument.Name)) : $"arg{i}"))
+ .WithType(
+ GetDotnetType(argument, AccessMode.Write, true))))));
}
BlockSyntax body = Block();
body = body.AddStatements(
- LocalDeclarationStatement(VariableDeclaration(ParseTypeName("MessageWriter"),
+ LocalDeclarationStatement(
+ VariableDeclaration(IdentifierName("MessageWriter"),
SingletonSeparatedList(
VariableDeclarator("writer")
.WithInitializer(EqualsValueClause(
@@ -675,15 +566,21 @@ namespace Tmds.DBus.SourceGenerator
ArgumentListSyntax args = ArgumentList()
.AddArguments(
- Argument(LiteralExpression(SyntaxKind.NullLiteralExpression)),
- Argument(IdentifierName("Path")),
- Argument(MakeLiteralExpression(dBusInterface.Name!)),
- Argument(MakeLiteralExpression(dBusSignal.Name!)));
-
- if (dBusSignal.Arguments?.Length > 0)
+ Argument(
+ LiteralExpression(SyntaxKind.NullLiteralExpression)),
+ Argument(
+ MakeMemberAccessExpression("PathHandler", "Path")),
+ Argument(
+ MakeLiteralExpression(dBusInterface.Name!)),
+ Argument(
+ MakeLiteralExpression(signal.Name!)));
+
+ if (signal.Arguments?.Length > 0)
{
args = args.AddArguments(
- Argument(MakeLiteralExpression(ParseSignature(dBusSignal.Arguments)!)));
+ Argument(
+ MakeLiteralExpression(
+ ParseSignature(signal.Arguments)!)));
}
body = body.AddStatements(
@@ -692,17 +589,19 @@ namespace Tmds.DBus.SourceGenerator
MakeMemberAccessExpression("writer", "WriteSignalHeader"))
.WithArgumentList(args)));
- if (dBusSignal.Arguments?.Length > 0)
+ if (signal.Arguments?.Length > 0)
{
- for (int i = 0; i < dBusSignal.Arguments.Length; i++)
+ for (int i = 0; i < signal.Arguments.Length; i++)
{
body = body.AddStatements(
ExpressionStatement(
InvocationExpression(
- MakeMemberAccessExpression("writer", GetOrAddWriteMethod(dBusSignal.Arguments[i])))
+ MakeMemberAccessExpression("writer", GetOrAddWriteMethod(signal.Arguments[i])))
.AddArgumentListArguments(
Argument(
- IdentifierName(dBusSignal.Arguments[i].Name ?? $"arg{i}")))));
+ IdentifierName(signal.Arguments[i].Name is not null
+ ? Camelize(signal.Arguments[i].Name!)
+ : $"arg{i}")))));
}
}
diff --git a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Parsing.cs b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Parsing.cs
index c4942fcca4..f1cc2f8457 100644
--- a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Parsing.cs
+++ b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Parsing.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
+using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
@@ -12,6 +13,21 @@ namespace Tmds.DBus.SourceGenerator
{
public partial class DBusSourceGenerator
{
+ private static readonly DBusValue _byteValue = new() { Type = "y" };
+ private static readonly DBusValue _boolValue = new() { Type = "b" };
+ private static readonly DBusValue _int16Value = new() { Type = "n" };
+ private static readonly DBusValue _uInt16Value = new() { Type = "q" };
+ private static readonly DBusValue _int32Value = new() { Type = "i" };
+ private static readonly DBusValue _uInt32Value = new() { Type = "u" };
+ private static readonly DBusValue _int64Value = new() { Type = "x" };
+ private static readonly DBusValue _uInt64Value = new() { Type = "t" };
+ private static readonly DBusValue _doubleValue = new() { Type = "d" };
+ private static readonly DBusValue _stringValue = new() { Type = "s" };
+ private static readonly DBusValue _objectPathValue = new() { Type = "o" };
+ private static readonly DBusValue _signatureValue = new() { Type = "g" };
+ private static readonly DBusValue _variantValue = new() { Type = "v" };
+ private static readonly DBusValue _unixFdValue = new() { Type = "h" };
+
private static string Pascalize(string name, bool camel = false)
{
bool upperizeNext = !camel;
@@ -38,71 +54,178 @@ namespace Tmds.DBus.SourceGenerator
return sb.ToString();
}
+ private static string Camelize(string name)
+ {
+ StringBuilder sb = new(Pascalize(name));
+ sb[0] = char.ToLowerInvariant(sb[0]);
+ return sb.ToString();
+ }
+
private static string? ParseSignature(IReadOnlyList? dBusValues)
{
if (dBusValues is null || dBusValues.Count == 0)
return null;
+
StringBuilder sb = new();
foreach (DBusValue dBusValue in dBusValues.Where(static argument => argument.Type is not null))
sb.Append(dBusValue.Type);
+
return sb.ToString();
}
- private static string? ParseReturnType(IReadOnlyList? dBusValues) => dBusValues?.Count switch
+ private static TypeSyntax? ParseReturnType(IReadOnlyList? dBusValues, AccessMode accessMode) => dBusValues?.Count switch
{
0 or null => null,
- 1 => dBusValues[0].DotNetType,
- _ => TupleOf(dBusValues.Select(static (x, i) => $"{x.DotNetType} {(x.Name is not null ? SanitizeIdentifier(x.Name) : $"Item{i + 1}")}"))
+ 1 => GetDotnetType(dBusValues[0], accessMode),
+ _ => TupleType()
+ .AddElements(
+ dBusValues.Select((dBusValue, i) => TupleElement(GetDotnetType(dBusValue, accessMode))
+ .WithIdentifier(
+ Identifier(dBusValue.Name is not null ? SanitizeIdentifier(Pascalize(dBusValue.Name)) : $"Item{i + 1}")))
+ .ToArray())
};
- private static string ParseTaskReturnType(DBusValue dBusValue) => ParseTaskReturnType(new[] { dBusValue });
+ private static TypeSyntax ParseTaskReturnType(IReadOnlyList? dBusValues, AccessMode accessMode) => dBusValues?.Count switch
+ {
+ 0 or null => IdentifierName("Task"),
+ _ => GenericName("Task")
+ .AddTypeArgumentListArguments(
+ ParseReturnType(dBusValues, accessMode)!)
+ };
- private static string ParseTaskReturnType(IReadOnlyList? dBusValues) => dBusValues?.Count switch
+ private static TypeSyntax ParseValueTaskReturnType(IReadOnlyList? dBusValues, AccessMode accessMode) => dBusValues?.Count switch
{
- 0 or null => "Task",
- 1 => $"Task<{dBusValues[0].DotNetType}>",
- _ => $"Task<{TupleOf(dBusValues.Select(static (x, i) => $"{x.DotNetType} {(x.Name is not null ? SanitizeIdentifier(x.Name) : $"Item{i + 1}")}"))}>"
+ 0 or null => IdentifierName("ValueTask"),
+ _ => GenericName("ValueTask")
+ .AddTypeArgumentListArguments(
+ ParseReturnType(dBusValues, accessMode)!)
};
- private static ParameterListSyntax ParseParameterList(IEnumerable inArgs) => ParameterList(
+ private static TypeSyntax ParseTaskCompletionSourceType(IReadOnlyList? dBusValues, AccessMode accessMode) => dBusValues?.Count switch
+ {
+ 0 or null => GenericName("TaskCompletionSource")
+ .AddTypeArgumentListArguments(
+ PredefinedType(
+ Token(SyntaxKind.BoolKeyword))),
+ _ => GenericName("TaskCompletionSource")
+ .AddTypeArgumentListArguments(
+ ParseReturnType(dBusValues, accessMode)!)
+ };
+
+ private static ParameterListSyntax ParseParameterList(IEnumerable inArgs, AccessMode accessMode) => ParameterList(
SeparatedList(
- inArgs.Select(static (x, i) =>
- Parameter(Identifier(x.Name is not null ? SanitizeIdentifier(x.Name) : $"arg{i}")).WithType(ParseTypeName(x.DotNetType)))));
+ inArgs.Select((x, i) =>
+ Parameter(Identifier(x.Name is not null ? SanitizeIdentifier(Camelize(x.Name)) : $"arg{i}")).WithType(GetDotnetType(x, accessMode)))));
private static string SanitizeSignature(string signature) =>
- signature.Replace('{', 'e').Replace("}", null).Replace('(', 'r').Replace(')', 'z');
+ signature.Replace('{', 'e')
+ .Replace("}", null)
+ .Replace('(', 'r')
+ .Replace(')', 'z');
- private static string SanitizeIdentifier(string identifier) => $"@{identifier}";
+ private static string SanitizeIdentifier(string identifier)
+ {
+ bool isAnyKeyword = SyntaxFacts.GetKeywordKind(identifier) != SyntaxKind.None || SyntaxFacts.GetContextualKeywordKind(identifier) != SyntaxKind.None;
+ return isAnyKeyword ? $"@{identifier}" : identifier;
+ }
- internal static (string DotnetType, string[] InnerDotNetTypes, DBusValue DBusValue, DBusValue[] InnerDBusTypes, DBusType DBusType) ParseDBusValue(string signature) =>
- SignatureReader.Transform<(string, string[], DBusValue, DBusValue[], DBusType)>(Encoding.ASCII.GetBytes(signature), MapDBusToDotNet);
+ internal static (DBusValue DBusValue, DBusValue[] InnerDBusTypes, DBusType DBusType) ParseDBusValue(string signature) =>
+ SignatureReader.Transform<(DBusValue, DBusValue[], DBusType)>(Encoding.ASCII.GetBytes(signature), MapDBusToDotNet);
- private static (string, string[], DBusValue, DBusValue[], DBusType) MapDBusToDotNet(DBusType dBusType, (string, string[], DBusValue, DBusValue[], DBusType)[] inner)
+ private static (DBusValue, DBusValue[], DBusType) MapDBusToDotNet(DBusType dBusType, (DBusValue, DBusValue[], DBusType)[] inner)
{
- string[] innerDotNetTypes = inner.Select(static x => x.Item1).ToArray();
- DBusValue[] innerDBusTypes = inner.Select(static x => x.Item3).ToArray();
+ DBusValue[] innerDBusTypes = inner.Select(static x => x.Item1).ToArray();
return dBusType switch
{
- DBusType.Byte => ("byte", innerDotNetTypes, new DBusValue { Type = "y" }, innerDBusTypes, dBusType),
- DBusType.Bool => ("bool", innerDotNetTypes, new DBusValue { Type = "b" }, innerDBusTypes, dBusType),
- DBusType.Int16 => ("short", innerDotNetTypes, new DBusValue { Type = "n" }, innerDBusTypes, dBusType),
- DBusType.UInt16 => ("ushort", innerDotNetTypes, new DBusValue { Type = "q" }, innerDBusTypes, dBusType),
- DBusType.Int32 => ("int", innerDotNetTypes, new DBusValue { Type = "i" }, innerDBusTypes, dBusType),
- DBusType.UInt32 => ("uint", innerDotNetTypes, new DBusValue { Type = "u" }, innerDBusTypes, dBusType),
- DBusType.Int64 => ("long", innerDotNetTypes, new DBusValue { Type = "x" }, innerDBusTypes, dBusType),
- DBusType.UInt64 => ("ulong", innerDotNetTypes, new DBusValue { Type = "t" }, innerDBusTypes, dBusType),
- DBusType.Double => ("double", innerDotNetTypes, new DBusValue { Type = "d" }, innerDBusTypes, dBusType),
- DBusType.String => ("string", innerDotNetTypes, new DBusValue { Type = "s" }, innerDBusTypes, dBusType),
- DBusType.ObjectPath => ("ObjectPath", innerDotNetTypes, new DBusValue { Type = "o" }, innerDBusTypes, dBusType),
- DBusType.Signature => ("Signature", innerDotNetTypes, new DBusValue { Type = "g" }, innerDBusTypes, dBusType),
- DBusType.Variant => ("DBusVariantItem", innerDotNetTypes, new DBusValue { Type = "v" }, innerDBusTypes, dBusType),
- DBusType.UnixFd => ("SafeHandle", innerDotNetTypes, new DBusValue { Type = "h" }, innerDBusTypes, dBusType),
- DBusType.Array => ($"{innerDotNetTypes[0]}[]", innerDotNetTypes, new DBusValue { Type = $"a{ParseSignature(innerDBusTypes)}" }, innerDBusTypes, dBusType),
- DBusType.DictEntry => ($"Dictionary<{innerDotNetTypes[0]}, {innerDotNetTypes[1]}>", innerDotNetTypes, new DBusValue { Type = $"a{{{ParseSignature(innerDBusTypes)}}}" }, innerDBusTypes, dBusType),
- DBusType.Struct when innerDotNetTypes.Length == 1 => ($"ValueTuple<{innerDotNetTypes[0]}>", innerDotNetTypes, new DBusValue { Type = $"({ParseSignature(innerDBusTypes)}" }, innerDBusTypes, dBusType),
- DBusType.Struct => ($"{TupleOf(innerDotNetTypes)}", innerDotNetTypes, new DBusValue { Type = $"({ParseSignature(innerDBusTypes)})" }, innerDBusTypes, dBusType),
- _ => throw new ArgumentOutOfRangeException(nameof(dBusType), dBusType, null)
+ DBusType.Byte => (_byteValue, innerDBusTypes, dBusType),
+ DBusType.Bool => (_boolValue, innerDBusTypes, dBusType),
+ DBusType.Int16 => (_int16Value, innerDBusTypes, dBusType),
+ DBusType.UInt16 => (_uInt16Value, innerDBusTypes, dBusType),
+ DBusType.Int32 => (_int32Value, innerDBusTypes, dBusType),
+ DBusType.UInt32 => (_uInt32Value, innerDBusTypes, dBusType),
+ DBusType.Int64 => (_int64Value, innerDBusTypes, dBusType),
+ DBusType.UInt64 => (_uInt64Value, innerDBusTypes, dBusType),
+ DBusType.Double => (_doubleValue, innerDBusTypes, dBusType),
+ DBusType.String => (_stringValue, innerDBusTypes, dBusType),
+ DBusType.ObjectPath => (_objectPathValue, innerDBusTypes, dBusType),
+ DBusType.Signature => (_signatureValue, innerDBusTypes, dBusType),
+ DBusType.Variant => (_variantValue, innerDBusTypes, dBusType),
+ DBusType.UnixFd => (_unixFdValue, innerDBusTypes, dBusType),
+ DBusType.Array => (new DBusValue { Type = $"a{ParseSignature(innerDBusTypes)}"}, innerDBusTypes, dBusType),
+ DBusType.DictEntry => (new DBusValue { Type = $"a{{{ParseSignature(innerDBusTypes)}}}"}, innerDBusTypes, dBusType),
+ DBusType.Struct => (new DBusValue { Type = $"({ParseSignature(innerDBusTypes)})"}, innerDBusTypes, dBusType),
+ _ => throw new ArgumentOutOfRangeException(nameof(dBusType), dBusType, $"Cannot parse DBusType with value {dBusType}")
};
}
+
+ private static TypeSyntax GetDotnetType(DBusValue dBusValue, AccessMode accessMode, bool nullable = false)
+ {
+ switch (dBusValue.DBusType)
+ {
+ case DBusType.Byte:
+ return PredefinedType(Token(SyntaxKind.ByteKeyword));
+ case DBusType.Bool:
+ return PredefinedType(Token(SyntaxKind.BoolKeyword));
+ case DBusType.Int16:
+ return PredefinedType(Token(SyntaxKind.ShortKeyword));
+ case DBusType.UInt16:
+ return PredefinedType(Token(SyntaxKind.UShortKeyword));
+ case DBusType.Int32:
+ return PredefinedType(Token(SyntaxKind.IntKeyword));
+ case DBusType.UInt32:
+ return PredefinedType(Token(SyntaxKind.UIntKeyword));
+ case DBusType.Int64:
+ return PredefinedType(Token(SyntaxKind.LongKeyword));
+ case DBusType.UInt64:
+ return PredefinedType(Token(SyntaxKind.ULongKeyword));
+ case DBusType.Double:
+ return PredefinedType(Token(SyntaxKind.DoubleKeyword));
+ case DBusType.String:
+ TypeSyntax str = PredefinedType(Token(SyntaxKind.StringKeyword));
+ if (nullable)
+ str = NullableType(str);
+ return str;
+ case DBusType.ObjectPath:
+ return IdentifierName("ObjectPath");
+ case DBusType.Signature:
+ return IdentifierName("Signature");
+ case DBusType.Variant when accessMode == AccessMode.Read:
+ return IdentifierName("VariantValue");
+ case DBusType.Variant when accessMode == AccessMode.Write:
+ return IdentifierName("Variant");
+ case DBusType.UnixFd:
+ return IdentifierName("SafeFileHandle");
+ case DBusType.Array:
+ TypeSyntax arr = ArrayType(
+ GetDotnetType(dBusValue.InnerDBusTypes![0], accessMode, nullable))
+ .AddRankSpecifiers(ArrayRankSpecifier()
+ .AddSizes(OmittedArraySizeExpression()));
+ if (nullable)
+ arr = NullableType(arr);
+ return arr;
+ case DBusType.DictEntry:
+ TypeSyntax dict = GenericName("Dictionary")
+ .AddTypeArgumentListArguments(
+ GetDotnetType(dBusValue.InnerDBusTypes![0], accessMode),
+ GetDotnetType(dBusValue.InnerDBusTypes![1], accessMode, nullable));
+ if (nullable)
+ dict = NullableType(dict);
+ return dict;
+ case DBusType.Struct when dBusValue.InnerDBusTypes!.Length == 1:
+ return GenericName("ValueTuple")
+ .AddTypeArgumentListArguments(
+ GetDotnetType(dBusValue.InnerDBusTypes![0], accessMode, nullable));
+ case DBusType.Struct:
+ return TupleType()
+ .AddElements(
+ dBusValue.InnerDBusTypes!.Select(
+ dbusType => TupleElement(
+ GetDotnetType(dbusType, accessMode, nullable)))
+ .ToArray());
+ default:
+ throw new ArgumentOutOfRangeException(nameof(dBusValue.DBusType), dBusValue.DBusType,
+ $"Cannot parse DBusType with value {dBusValue.DBusType}");
+ }
+ }
}
}
diff --git a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Proxy.cs b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Proxy.cs
index a04721b638..49b6ff5c78 100644
--- a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Proxy.cs
+++ b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Proxy.cs
@@ -1,4 +1,3 @@
-using System;
using System.Collections.Generic;
using System.Linq;
@@ -19,16 +18,21 @@ namespace Tmds.DBus.SourceGenerator
.AddModifiers(Token(SyntaxKind.InternalKeyword));
FieldDeclarationSyntax interfaceConst = MakePrivateStringConst("Interface", dBusInterface.Name!, PredefinedType(Token(SyntaxKind.StringKeyword)));
- FieldDeclarationSyntax connectionField = MakePrivateReadOnlyField("_connection", ParseTypeName("Connection"));
+ FieldDeclarationSyntax connectionField = MakePrivateReadOnlyField("_connection", IdentifierName("Connection"));
FieldDeclarationSyntax destinationField = MakePrivateReadOnlyField("_destination", PredefinedType(Token(SyntaxKind.StringKeyword)));
FieldDeclarationSyntax pathField = MakePrivateReadOnlyField("_path", PredefinedType(Token(SyntaxKind.StringKeyword)));
ConstructorDeclarationSyntax ctor = ConstructorDeclaration(identifier)
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddParameterListParameters(
- Parameter(Identifier("connection")).WithType(ParseTypeName("Connection")),
- Parameter(Identifier("destination")).WithType(PredefinedType(Token(SyntaxKind.StringKeyword))),
- Parameter(Identifier("path")).WithType(PredefinedType(Token(SyntaxKind.StringKeyword))))
+ Parameter(Identifier("connection"))
+ .WithType(IdentifierName("Connection")),
+ Parameter(Identifier("destination"))
+ .WithType(
+ PredefinedType(Token(SyntaxKind.StringKeyword))),
+ Parameter(Identifier("path"))
+ .WithType(
+ PredefinedType(Token(SyntaxKind.StringKeyword))))
.WithBody(
Block(
MakeAssignmentExpressionStatement("_connection", "connection"),
@@ -36,9 +40,10 @@ namespace Tmds.DBus.SourceGenerator
MakeAssignmentExpressionStatement("_path", "path")));
cl = cl.AddMembers(interfaceConst, connectionField, destinationField, pathField, ctor);
+
+ AddProperties(ref cl, dBusInterface);
AddProxyMethods(ref cl, dBusInterface);
AddProxySignals(ref cl, dBusInterface);
- AddProperties(ref cl, dBusInterface);
return cl;
}
@@ -47,13 +52,12 @@ namespace Tmds.DBus.SourceGenerator
{
if (dBusInterface.Methods is null)
return;
+
foreach (DBusMethod dBusMethod in dBusInterface.Methods)
{
DBusArgument[]? inArgs = dBusMethod.Arguments?.Where(static m => m.Direction is null or "in").ToArray();
DBusArgument[]? outArgs = dBusMethod.Arguments?.Where(static m => m.Direction == "out").ToArray();
- string returnType = ParseTaskReturnType(outArgs);
-
ArgumentListSyntax args = ArgumentList(
SingletonSeparatedList(
Argument(
@@ -67,21 +71,21 @@ namespace Tmds.DBus.SourceGenerator
MakeMemberAccessExpression("ReaderExtensions", GetOrAddReadMessageMethod(outArgs))));
}
- StatementSyntax[] statements = inArgs?.Select((x, i) => ExpressionStatement(
+ StatementSyntax[] statements = inArgs?.Select((arg, i) => ExpressionStatement(
InvocationExpression(
- MakeMemberAccessExpression("writer", GetOrAddWriteMethod(x)))
+ MakeMemberAccessExpression("writer", GetOrAddWriteMethod(arg)))
.AddArgumentListArguments(
- Argument(IdentifierName(x.Name is not null ? SanitizeIdentifier(x.Name) : $"arg{i}")))))
+ Argument(IdentifierName(arg.Name is not null ? SanitizeIdentifier(Camelize(arg.Name)) : $"arg{i}")))))
.Cast()
- .ToArray() ?? Array.Empty();
+ .ToArray() ?? [];
BlockSyntax createMessageBody = MakeCreateMessageBody(IdentifierName("Interface"), dBusMethod.Name!, ParseSignature(inArgs), statements);
- MethodDeclarationSyntax proxyMethod = MethodDeclaration(ParseTypeName(returnType), $"{Pascalize(dBusMethod.Name!)}Async")
+ MethodDeclarationSyntax proxyMethod = MethodDeclaration(ParseTaskReturnType(outArgs, AccessMode.Read), $"{Pascalize(dBusMethod.Name!)}Async")
.AddModifiers(Token(SyntaxKind.PublicKeyword));
if (inArgs is not null)
- proxyMethod = proxyMethod.WithParameterList(ParseParameterList(inArgs));
+ proxyMethod = proxyMethod.WithParameterList(ParseParameterList(inArgs, AccessMode.Write));
cl = cl.AddMembers(proxyMethod.WithBody(MakeCallMethodReturnBody(args, createMessageBody)));
}
@@ -89,48 +93,69 @@ namespace Tmds.DBus.SourceGenerator
private void AddProxySignals(ref ClassDeclarationSyntax cl, DBusInterface dBusInterface)
{
- if (dBusInterface.Signals is null) return;
+ if (dBusInterface.Signals is null)
+ return;
+
foreach (DBusSignal dBusSignal in dBusInterface.Signals)
{
DBusArgument[]? outArgs = dBusSignal.Arguments?.Where(static x => x.Direction is null or "out").ToArray();
- string? returnType = ParseReturnType(outArgs);
+ TypeSyntax? returnType = ParseReturnType(outArgs, AccessMode.Read);
ParameterListSyntax parameters = ParameterList();
parameters = returnType is not null
? parameters.AddParameters(
Parameter(Identifier("handler"))
- .WithType(ParseTypeName($"Action")))
+ .WithType(
+ GenericName("Action")
+ .AddTypeArgumentListArguments(
+ NullableType(
+ IdentifierName("Exception")),
+ returnType)))
: parameters.AddParameters(
Parameter(Identifier("handler"))
- .WithType(ParseTypeName("Action")));
+ .WithType(
+ GenericName("Action")
+ .AddTypeArgumentListArguments(
+ NullableType(
+ IdentifierName("Exception")))));
parameters = parameters.AddParameters(
Parameter(Identifier("emitOnCapturedContext"))
.WithType(PredefinedType(Token(SyntaxKind.BoolKeyword)))
- .WithDefault(EqualsValueClause(LiteralExpression(SyntaxKind.TrueLiteralExpression))));
+ .WithDefault(EqualsValueClause(LiteralExpression(SyntaxKind.TrueLiteralExpression))),
+ Parameter(Identifier("flags"))
+ .WithType(IdentifierName("ObserverFlags"))
+ .WithDefault(EqualsValueClause(MakeMemberAccessExpression("ObserverFlags", "None"))));
ArgumentListSyntax arguments = ArgumentList()
- .AddArguments(Argument(IdentifierName("_connection")),
+ .AddArguments(
+ Argument(IdentifierName("_connection")),
Argument(IdentifierName("rule")));
if (outArgs is not null)
{
arguments = arguments.AddArguments(
- Argument(MakeMemberAccessExpression("ReaderExtensions", GetOrAddReadMessageMethod(outArgs))));
+ Argument(
+ MakeMemberAccessExpression("ReaderExtensions", GetOrAddReadMessageMethod(outArgs))));
}
arguments = arguments.AddArguments(
Argument(IdentifierName("handler")),
- Argument(IdentifierName("emitOnCapturedContext")));
-
- MethodDeclarationSyntax watchSignalMethod = MethodDeclaration(ParseTypeName("ValueTask"), $"Watch{Pascalize(dBusSignal.Name!)}Async")
+ Argument(IdentifierName("emitOnCapturedContext")),
+ Argument(IdentifierName("flags")));
+
+ MethodDeclarationSyntax watchSignalMethod = MethodDeclaration(
+ GenericName("ValueTask")
+ .AddTypeArgumentListArguments(
+ IdentifierName("IDisposable")),
+ $"Watch{Pascalize(dBusSignal.Name!)}Async")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.WithParameterList(parameters)
.WithBody(
Block(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("MatchRule"))
+ VariableDeclaration(IdentifierName("MatchRule"))
.AddVariables(
VariableDeclarator("rule")
.WithInitializer(
@@ -145,7 +170,7 @@ namespace Tmds.DBus.SourceGenerator
}
private static ObjectCreationExpressionSyntax MakeMatchRule(DBusSignal dBusSignal) =>
- ObjectCreationExpression(ParseTypeName("MatchRule"))
+ ObjectCreationExpression(IdentifierName("MatchRule"))
.WithInitializer(
InitializerExpression(SyntaxKind.ObjectInitializerExpression)
.AddExpressions(
@@ -156,78 +181,106 @@ namespace Tmds.DBus.SourceGenerator
MakeAssignmentExpression(IdentifierName("Interface"), IdentifierName("Interface"))));
private void AddWatchPropertiesChanged(ref ClassDeclarationSyntax cl) =>
- cl = cl.AddMembers(MethodDeclaration(ParseTypeName("ValueTask"), "WatchPropertiesChangedAsync")
- .AddModifiers(Token(SyntaxKind.PublicKeyword))
- .AddParameterListParameters(
- Parameter(Identifier("handler"))
- .WithType(ParseTypeName("Action>")),
- Parameter(Identifier("emitOnCapturedContext"))
- .WithType(PredefinedType(Token(SyntaxKind.BoolKeyword)))
- .WithDefault(
- EqualsValueClause(
- LiteralExpression(SyntaxKind.TrueLiteralExpression))))
- .WithBody(
- Block(
- ReturnStatement(
- InvocationExpression(
- MakeMemberAccessExpression("SignalHelper", "WatchPropertiesChangedAsync"))
- .AddArgumentListArguments(
- Argument(IdentifierName("_connection")),
- Argument(IdentifierName("_destination")),
- Argument(IdentifierName("_path")),
- Argument(IdentifierName("Interface")),
- Argument(IdentifierName("ReadMessage")),
- Argument(IdentifierName("handler")),
- Argument(IdentifierName("emitOnCapturedContext")))),
- LocalFunctionStatement(ParseTypeName("PropertyChanges"), "ReadMessage")
- .AddModifiers(Token(SyntaxKind.StaticKeyword))
- .AddParameterListParameters(
- Parameter(Identifier("message"))
- .WithType(ParseTypeName("Message")),
- Parameter(Identifier("_"))
- .WithType(
- NullableType(
- PredefinedType(Token(SyntaxKind.ObjectKeyword)))))
- .WithBody(
- Block(
- LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("Reader"))
- .AddVariables(
- VariableDeclarator("reader")
- .WithInitializer(
- EqualsValueClause(
- InvocationExpression(
- MakeMemberAccessExpression("message", "GetBodyReader")))))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("reader", "ReadString"))),
- LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("List"))
- .AddVariables(
- VariableDeclarator("changed")
- .WithInitializer(
- EqualsValueClause(
- ImplicitObjectCreationExpression())))),
- ReturnStatement(
- InvocationExpression(
- ObjectCreationExpression(ParseTypeName("PropertyChanges")))
- .AddArgumentListArguments(
- Argument(InvocationExpression(
- IdentifierName("ReadProperties"))
- .AddArgumentListArguments(
- Argument(IdentifierName("reader"))
- .WithRefKindKeyword(Token(SyntaxKind.RefKeyword)),
- Argument(IdentifierName("changed")))),
- Argument(
- InvocationExpression(
- MakeMemberAccessExpression("changed", "ToArray"))),
- Argument(
- InvocationExpression(
- MakeMemberAccessExpression("reader", GetOrAddReadMethod(new DBusValue { Type = "as" })))))))))));
+ cl = cl.AddMembers(
+ MethodDeclaration(
+ GenericName("ValueTask")
+ .AddTypeArgumentListArguments(
+ IdentifierName("IDisposable")),
+ "WatchPropertiesChangedAsync")
+ .AddModifiers(Token(SyntaxKind.PublicKeyword))
+ .AddParameterListParameters(
+ Parameter(Identifier("handler"))
+ .WithType(GenericName("Action")
+ .AddTypeArgumentListArguments(
+ NullableType(
+ IdentifierName("Exception")),
+ GenericName("PropertyChanges")
+ .AddTypeArgumentListArguments(
+ IdentifierName("Properties")))),
+ Parameter(Identifier("emitOnCapturedContext"))
+ .WithType(PredefinedType(Token(SyntaxKind.BoolKeyword)))
+ .WithDefault(
+ EqualsValueClause(
+ LiteralExpression(SyntaxKind.TrueLiteralExpression))),
+ Parameter(Identifier("flags"))
+ .WithType(IdentifierName("ObserverFlags"))
+ .WithDefault(
+ EqualsValueClause(
+ MakeMemberAccessExpression("ObserverFlags", "None"))))
+ .WithBody(
+ Block(
+ ReturnStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("SignalHelper", "WatchPropertiesChangedAsync"))
+ .AddArgumentListArguments(
+ Argument(IdentifierName("_connection")),
+ Argument(IdentifierName("_destination")),
+ Argument(IdentifierName("_path")),
+ Argument(IdentifierName("Interface")),
+ Argument(IdentifierName("ReadMessage")),
+ Argument(IdentifierName("handler")),
+ Argument(IdentifierName("emitOnCapturedContext")),
+ Argument(IdentifierName("flags")))),
+ LocalFunctionStatement(
+ GenericName("PropertyChanges")
+ .AddTypeArgumentListArguments(
+ IdentifierName("Properties")),
+ "ReadMessage")
+ .AddModifiers(Token(SyntaxKind.StaticKeyword))
+ .AddParameterListParameters(
+ Parameter(Identifier("message"))
+ .WithType(IdentifierName("Message")),
+ Parameter(Identifier("_"))
+ .WithType(
+ NullableType(
+ PredefinedType(Token(SyntaxKind.ObjectKeyword)))))
+ .WithBody(
+ Block(
+ LocalDeclarationStatement(
+ VariableDeclaration(IdentifierName("Reader"))
+ .AddVariables(
+ VariableDeclarator("reader")
+ .WithInitializer(
+ EqualsValueClause(
+ InvocationExpression(
+ MakeMemberAccessExpression("message", "GetBodyReader")))))),
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("reader", "ReadString"))),
+ LocalDeclarationStatement(
+ VariableDeclaration(
+ GenericName("List")
+ .AddTypeArgumentListArguments(
+ PredefinedType(Token(SyntaxKind.StringKeyword))))
+ .AddVariables(
+ VariableDeclarator("changed")
+ .WithInitializer(
+ EqualsValueClause(
+ ImplicitObjectCreationExpression())))),
+ ReturnStatement(
+ InvocationExpression(
+ ObjectCreationExpression(GenericName("PropertyChanges")
+ .AddTypeArgumentListArguments(
+ IdentifierName("Properties"))))
+ .AddArgumentListArguments(
+ Argument(InvocationExpression(
+ IdentifierName("ReadProperties"))
+ .AddArgumentListArguments(
+ Argument(IdentifierName("reader"))
+ .WithRefKindKeyword(Token(SyntaxKind.RefKeyword)),
+ Argument(IdentifierName("changed")))),
+ Argument(
+ InvocationExpression(
+ MakeMemberAccessExpression("changed", "ToArray"))),
+ Argument(
+ InvocationExpression(
+ MakeMemberAccessExpression("reader",
+ GetOrAddReadMethod(new DBusValue { Type = "as" })))))))))));
private void AddProperties(ref ClassDeclarationSyntax cl, DBusInterface dBusInterface)
{
- if (dBusInterface.Properties is null || dBusInterface.Properties.Length == 0) return;
+ if (dBusInterface.Properties is null || dBusInterface.Properties.Length == 0)
+ return;
cl = dBusInterface.Properties!.Aggregate(cl, (current, dBusProperty) => dBusProperty.Access switch
{
@@ -263,7 +316,7 @@ namespace Tmds.DBus.SourceGenerator
Argument(
MakeMemberAccessExpression("ReaderExtensions", GetOrAddReadMessageMethod(dBusProperty, true))));
- return MethodDeclaration(ParseTypeName(ParseTaskReturnType(dBusProperty)), $"Get{Pascalize(dBusProperty.Name!)}PropertyAsync")
+ return MethodDeclaration(ParseTaskReturnType([dBusProperty], AccessMode.Read), $"Get{Pascalize(dBusProperty.Name!)}PropertyAsync")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.WithBody(
MakeCallMethodReturnBody(args, createMessageBody));
@@ -279,7 +332,7 @@ namespace Tmds.DBus.SourceGenerator
ExpressionStatement(
InvocationExpression(
MakeMemberAccessExpression("writer", "WriteString"))
- .AddArgumentListArguments(Argument(MakeLiteralExpression(dBusProperty.Name!)))),
+ .AddArgumentListArguments(Argument(MakeLiteralExpression(Pascalize(dBusProperty.Name!))))),
ExpressionStatement(
InvocationExpression(
MakeMemberAccessExpression("writer", "WriteVariant"))
@@ -291,10 +344,13 @@ namespace Tmds.DBus.SourceGenerator
InvocationExpression(
IdentifierName("CreateMessage")))));
- return MethodDeclaration(ParseTypeName("Task"), $"Set{dBusProperty.Name}PropertyAsync")
+ return MethodDeclaration(
+ IdentifierName("Task"),
+ $"Set{Pascalize(dBusProperty.Name!)}PropertyAsync")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddParameterListParameters(
- Parameter(Identifier("value")).WithType(ParseTypeName(dBusProperty.DotNetType)))
+ Parameter(Identifier("value"))
+ .WithType(GetDotnetType(dBusProperty, AccessMode.Write)))
.WithBody(
MakeCallMethodReturnBody(args, createMessageBody));
}
@@ -309,26 +365,34 @@ namespace Tmds.DBus.SourceGenerator
ParenthesizedLambdaExpressionSyntax messageValueReaderLambda = ParenthesizedLambdaExpression()
.AddParameterListParameters(
- Parameter(Identifier("message")).WithType(ParseTypeName("Message")),
- Parameter(Identifier("state")).WithType(NullableType(PredefinedType(Token(SyntaxKind.ObjectKeyword)))))
+ Parameter(Identifier("message"))
+ .WithType(IdentifierName("Message")),
+ Parameter(Identifier("state"))
+ .WithType(
+ NullableType(PredefinedType(Token(SyntaxKind.ObjectKeyword)))))
.WithBody(
Block(
- LocalDeclarationStatement(VariableDeclaration(ParseTypeName("Reader"))
- .AddVariables(
- VariableDeclarator("reader")
- .WithInitializer(
- EqualsValueClause(
- InvocationExpression(
- MakeMemberAccessExpression("message", "GetBodyReader")))))),
+ LocalDeclarationStatement(
+ VariableDeclaration(IdentifierName("Reader"))
+ .AddVariables(
+ VariableDeclarator("reader")
+ .WithInitializer(
+ EqualsValueClause(
+ InvocationExpression(
+ MakeMemberAccessExpression("message", "GetBodyReader")))))),
ReturnStatement(
InvocationExpression(
- IdentifierName("ReadProperties"))
+ IdentifierName("ReadProperties"))
.AddArgumentListArguments(
Argument(IdentifierName("reader"))
.WithRefKindKeyword(Token(SyntaxKind.RefKeyword))))));
cl = cl.AddMembers(
- MethodDeclaration(ParseTypeName("Task"), "GetAllPropertiesAsync")
+ MethodDeclaration(
+ GenericName("Task")
+ .AddTypeArgumentListArguments(
+ IdentifierName("Properties")),
+ "GetAllPropertiesAsync")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.WithBody(
Block(
@@ -336,9 +400,10 @@ namespace Tmds.DBus.SourceGenerator
InvocationExpression(
MakeMemberAccessExpression("_connection", "CallMethodAsync"))
.AddArgumentListArguments(
- Argument(InvocationExpression(IdentifierName("CreateGetAllMessage"))),
+ Argument(
+ InvocationExpression(IdentifierName("CreateGetAllMessage"))),
Argument(messageValueReaderLambda))),
- LocalFunctionStatement(ParseTypeName("MessageBuffer"), "CreateGetAllMessage")
+ LocalFunctionStatement(IdentifierName("MessageBuffer"), "CreateGetAllMessage")
.WithBody(createGetAllMessageBody))));
}
@@ -347,36 +412,41 @@ namespace Tmds.DBus.SourceGenerator
ClassDeclarationSyntax propertiesClass = ClassDeclaration("Properties")
.AddModifiers(Token(SyntaxKind.PublicKeyword));
- propertiesClass = dBusInterface.Properties!.Aggregate(propertiesClass, static (current, property)
- => current.AddMembers(
- MakeGetSetProperty(ParseTypeName(property.DotNetType), property.Name!, Token(SyntaxKind.PublicKeyword))));
+ propertiesClass = dBusInterface.Properties!.Aggregate(propertiesClass, static (current, property) =>
+ current.AddMembers(
+ MakeGetSetProperty(GetDotnetType(property, AccessMode.Read), Pascalize(property.Name!), Token(SyntaxKind.PublicKeyword))));
cl = cl.AddMembers(propertiesClass);
}
private void AddReadProperties(ref ClassDeclarationSyntax cl, IEnumerable dBusProperties) =>
cl = cl.AddMembers(
- MethodDeclaration(ParseTypeName("Properties"), "ReadProperties")
+ MethodDeclaration(
+ IdentifierName("Properties"), "ReadProperties")
.AddModifiers(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
Parameter(Identifier("reader"))
- .WithType(ParseTypeName("Reader"))
+ .WithType(IdentifierName("Reader"))
.AddModifiers(Token(SyntaxKind.RefKeyword)),
Parameter(Identifier("changed"))
- .WithType(NullableType(ParseTypeName("List")))
+ .WithType(
+ NullableType(
+ GenericName("List")
+ .AddTypeArgumentListArguments(
+ PredefinedType(Token(SyntaxKind.StringKeyword)))))
.WithDefault(
EqualsValueClause(
LiteralExpression(SyntaxKind.NullLiteralExpression))))
.WithBody(
Block(
- LocalDeclarationStatement(VariableDeclaration(ParseTypeName("Properties"))
+ LocalDeclarationStatement(VariableDeclaration(IdentifierName("Properties"))
.AddVariables(
VariableDeclarator("props")
.WithInitializer(
EqualsValueClause(
InvocationExpression(
- ObjectCreationExpression(ParseTypeName("Properties"))))))),
- LocalDeclarationStatement(VariableDeclaration(ParseTypeName("ArrayEnd"))
+ ObjectCreationExpression(IdentifierName("Properties"))))))),
+ LocalDeclarationStatement(VariableDeclaration(IdentifierName("ArrayEnd"))
.AddVariables(
VariableDeclarator("headersEnd")
.WithInitializer(
@@ -395,28 +465,30 @@ namespace Tmds.DBus.SourceGenerator
MakeMemberAccessExpression("reader", "ReadString")))
.WithSections(
List(
- dBusProperties.Select(x => SwitchSection()
+ dBusProperties.Select(property => SwitchSection()
.AddLabels(
CaseSwitchLabel(
- MakeLiteralExpression(x.Name!)))
+ MakeLiteralExpression(property.Name!)))
.AddStatements(
ExpressionStatement(
InvocationExpression(
MakeMemberAccessExpression("reader", "ReadSignature"))
.AddArgumentListArguments(
- Argument(MakeLiteralExpression(x.Type!)))),
+ Argument(
+ MakeLiteralExpression(property.Type!)))),
ExpressionStatement(
AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
- MakeMemberAccessExpression("props", x.Name!),
+ MakeMemberAccessExpression("props", Pascalize(property.Name!)),
InvocationExpression(
- MakeMemberAccessExpression("reader", GetOrAddReadMethod(x))))),
+ MakeMemberAccessExpression("reader", GetOrAddReadMethod(property))))),
ExpressionStatement(
ConditionalAccessExpression(
IdentifierName("changed"), InvocationExpression(
MemberBindingExpression(
IdentifierName("Add")))
.AddArgumentListArguments(
- Argument(MakeLiteralExpression(x.Name!))))),
+ Argument(
+ MakeLiteralExpression(Pascalize(property.Name!)))))),
BreakStatement())))))),
ReturnStatement(IdentifierName("props")))));
@@ -426,7 +498,7 @@ namespace Tmds.DBus.SourceGenerator
InvocationExpression(
MakeMemberAccessExpression("_connection", "CallMethodAsync"))
.WithArgumentList(args)),
- LocalFunctionStatement(ParseTypeName("MessageBuffer"), "CreateMessage")
+ LocalFunctionStatement(IdentifierName("MessageBuffer"), "CreateMessage")
.WithBody(createMessageBody));
private static BlockSyntax MakeCreateMessageBody(ExpressionSyntax interfaceExpression, string methodName, string? signature, params StatementSyntax[] statements)
@@ -443,7 +515,7 @@ namespace Tmds.DBus.SourceGenerator
return Block(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("MessageWriter"),
+ VariableDeclaration(IdentifierName("MessageWriter"),
SingletonSeparatedList(
VariableDeclarator("writer")
.WithInitializer(EqualsValueClause(
@@ -456,7 +528,7 @@ namespace Tmds.DBus.SourceGenerator
.AddStatements(statements)
.AddStatements(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("MessageBuffer"))
+ VariableDeclaration(IdentifierName("MessageBuffer"))
.AddVariables(
VariableDeclarator("message")
.WithInitializer(
diff --git a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Utils.cs b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Utils.cs
index 98ae13a84c..7a9bb92123 100644
--- a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Utils.cs
+++ b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.Utils.cs
@@ -22,6 +22,7 @@ namespace Tmds.DBus.SourceGenerator
UsingDirective(IdentifierName("System.Runtime.InteropServices")),
UsingDirective(IdentifierName("System.Threading")),
UsingDirective(IdentifierName("System.Threading.Tasks")),
+ UsingDirective(IdentifierName("Microsoft.Win32.SafeHandles")),
UsingDirective(IdentifierName("Tmds.DBus.Protocol")))
.AddMembers(namespaceDeclaration
.WithLeadingTrivia(
@@ -72,104 +73,8 @@ namespace Tmds.DBus.SourceGenerator
private static LiteralExpressionSyntax MakeLiteralExpression(string literal) => LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(literal));
- private static LiteralExpressionSyntax MakeLiteralExpression(int literal) => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(literal));
-
private static SyntaxToken Utf8Literal(string value) => Token(TriviaList(ElasticMarker), SyntaxKind.Utf8StringLiteralToken, SymbolDisplay.FormatLiteral(value, true) + "u8", value, TriviaList(ElasticMarker));
- private static string TupleOf(IEnumerable elements) => $"({string.Join(", ", elements)})";
-
- private static ExpressionSyntax MakeGetDBusVariantExpression(DBusValue dBusValue, ExpressionSyntax accessValueExpression) =>
- dBusValue.DBusType switch
- {
- DBusType.Byte => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusByteItem")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.Bool => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusBoolItem")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.Int16 => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusInt16Item")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.UInt16 => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusUInt16Item")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.Int32 => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusInt32Item")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.UInt32 => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusUInt32Item")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.Int64 => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusInt64Item")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.UInt64 => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusUInt64Item")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.Double => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusDoubleItem"))).
- AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.String => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusStringItem")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.ObjectPath => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusObjectPathItem")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.Signature => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusSignatureItem")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.Variant => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusVariantItem")))
- .AddArgumentListArguments(Argument(accessValueExpression)),
- DBusType.Array => ObjectCreationExpression(
- ParseTypeName("DBusArrayItem"))
- .AddArgumentListArguments(
- Argument(MakeMemberAccessExpression("DBusType", Enum.GetName(typeof(DBusType), dBusValue.InnerDBusTypes![0].DBusType)!)),
- Argument(
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
- InvocationExpression(
- MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, accessValueExpression, IdentifierName("Select")))
- .AddArgumentListArguments(
- Argument(
- SimpleLambdaExpression(
- Parameter(
- Identifier("x")))
- .WithExpressionBody(
- MakeGetDBusVariantExpression(dBusValue.InnerDBusTypes![0], IdentifierName("x"))))), IdentifierName("ToArray"))))),
- DBusType.DictEntry => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusDictEntryItem")))
- .AddArgumentListArguments(
- Argument(
- MakeGetDBusVariantExpression(dBusValue.InnerDBusTypes![0], MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, accessValueExpression, IdentifierName("Key")))),
- Argument(
- MakeGetDBusVariantExpression(dBusValue.InnerDBusTypes![1], MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, accessValueExpression, IdentifierName("Value"))))),
- DBusType.Struct => InvocationExpression(
- ObjectCreationExpression(
- ParseTypeName("DBusStructItem")))
- .AddArgumentListArguments(
- Argument(
- ObjectCreationExpression(ParseTypeName("DBusItem[]"))
- .WithInitializer(
- InitializerExpression(SyntaxKind.ArrayInitializerExpression, SeparatedList(
- dBusValue.InnerDBusTypes!.Select((x, i) =>
- MakeGetDBusVariantExpression(x, MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, accessValueExpression, IdentifierName($"Item{i + 1}"))))))))),
- _ => throw new ArgumentOutOfRangeException(nameof(dBusValue.DBusType), dBusValue.DBusType, "")
- };
-
private string GetOrAddWriteMethod(DBusValue dBusValue) =>
dBusValue.DBusType switch
{
@@ -182,15 +87,15 @@ namespace Tmds.DBus.SourceGenerator
DBusType.Int64 => "WriteInt64",
DBusType.UInt64 => "WriteUInt64",
DBusType.Double => "WriteDouble",
- DBusType.String => "WriteString",
- DBusType.ObjectPath => "WriteObjectPath",
+ DBusType.String => "WriteNullableString",
+ DBusType.ObjectPath => "WriteObjectPathSafe",
DBusType.Signature => "WriteSignature",
DBusType.UnixFd => "WriteHandle",
- DBusType.Variant => "WriteDBusVariant",
+ DBusType.Variant => "WriteVariant",
DBusType.Array => GetOrAddWriteArrayMethod(dBusValue),
DBusType.DictEntry => GetOrAddWriteDictionaryMethod(dBusValue),
DBusType.Struct => GetOrAddWriteStructMethod(dBusValue),
- _ => throw new ArgumentOutOfRangeException(nameof(dBusValue.DBusType), dBusValue.DBusType, "")
+ _ => throw new ArgumentOutOfRangeException(nameof(dBusValue.DBusType), dBusValue.DBusType, null)
};
private string GetOrAddReadMethod(DBusValue dBusValue) =>
@@ -208,12 +113,12 @@ namespace Tmds.DBus.SourceGenerator
DBusType.String => "ReadString",
DBusType.ObjectPath => "ReadObjectPath",
DBusType.Signature => "ReadSignature",
- DBusType.UnixFd => "ReadHandle",
- DBusType.Variant => "ReadDBusVariant",
+ DBusType.UnixFd => "ReadHandle",
+ DBusType.Variant => "ReadVariantValue",
DBusType.Array => GetOrAddReadArrayMethod(dBusValue),
DBusType.DictEntry => GetOrAddReadDictionaryMethod(dBusValue),
DBusType.Struct => GetOrAddReadStructMethod(dBusValue),
- _ => throw new ArgumentOutOfRangeException(nameof(dBusValue.DBusType), dBusValue.DBusType, "")
+ _ => throw new ArgumentOutOfRangeException(nameof(dBusValue.DBusType), dBusValue.DBusType, null)
};
private string GetOrAddReadArrayMethod(DBusValue dBusValue)
@@ -223,24 +128,26 @@ namespace Tmds.DBus.SourceGenerator
return identifier;
_readMethodExtensions.Add(identifier,
- MethodDeclaration(ParseTypeName(dBusValue.DotNetType), identifier)
+ MethodDeclaration(GetDotnetType(dBusValue, AccessMode.Read), identifier)
.AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
Parameter(Identifier("reader"))
- .WithType(ParseTypeName("Reader"))
+ .WithType(IdentifierName("Reader"))
.AddModifiers(Token(SyntaxKind.ThisKeyword), Token(SyntaxKind.RefKeyword)))
.WithBody(
Block()
.AddStatements(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName($"List<{dBusValue.InnerDBusTypes![0].DotNetType}>"))
+ VariableDeclaration(GenericName("List")
+ .AddTypeArgumentListArguments(
+ GetDotnetType(dBusValue.InnerDBusTypes![0], AccessMode.Read)))
.AddVariables(
VariableDeclarator("items")
.WithInitializer(
EqualsValueClause(
ImplicitObjectCreationExpression())))),
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("ArrayEnd"))
+ VariableDeclaration(IdentifierName("ArrayEnd"))
.AddVariables(
VariableDeclarator("headersEnd")
.WithInitializer(
@@ -277,24 +184,24 @@ namespace Tmds.DBus.SourceGenerator
return identifier;
_readMethodExtensions.Add(identifier,
- MethodDeclaration(ParseTypeName(dBusValue.DotNetType), identifier)
+ MethodDeclaration(GetDotnetType(dBusValue, AccessMode.Read), identifier)
.AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
Parameter(Identifier("reader"))
- .WithType(ParseTypeName("Reader"))
+ .WithType(IdentifierName("Reader"))
.AddModifiers(Token(SyntaxKind.ThisKeyword), Token(SyntaxKind.RefKeyword)))
.WithBody(
Block()
.AddStatements(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName(dBusValue.DotNetType))
+ VariableDeclaration(GetDotnetType(dBusValue, AccessMode.Read))
.AddVariables(
VariableDeclarator("items")
.WithInitializer(
EqualsValueClause(
ImplicitObjectCreationExpression())))),
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("ArrayEnd"))
+ VariableDeclaration(IdentifierName("ArrayEnd"))
.AddVariables(
VariableDeclarator("headersEnd")
.WithInitializer(
@@ -332,11 +239,11 @@ namespace Tmds.DBus.SourceGenerator
return identifier;
_readMethodExtensions.Add(identifier,
- MethodDeclaration(ParseTypeName(dBusValue.DotNetType), identifier)
+ MethodDeclaration(GetDotnetType(dBusValue, AccessMode.Read), identifier)
.AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
Parameter(Identifier("reader"))
- .WithType(ParseTypeName("Reader"))
+ .WithType(IdentifierName("Reader"))
.AddModifiers(Token(SyntaxKind.ThisKeyword), Token(SyntaxKind.RefKeyword)))
.WithBody(
Block()
@@ -345,13 +252,19 @@ namespace Tmds.DBus.SourceGenerator
InvocationExpression(
MakeMemberAccessExpression("reader", "AlignStruct"))),
ReturnStatement(
- InvocationExpression(
- MakeMemberAccessExpression("ValueTuple", "Create"))
- .AddArgumentListArguments(
- dBusValue.InnerDBusTypes!.Select(
- x => Argument(
+ dBusValue.InnerDBusTypes!.Length == 1
+ ? ObjectCreationExpression(
+ GetDotnetType(dBusValue, AccessMode.Read))
+ .AddArgumentListArguments(
+ Argument(
InvocationExpression(
- MakeMemberAccessExpression("reader", GetOrAddReadMethod(x))))).ToArray())))));
+ MakeMemberAccessExpression("reader", GetOrAddReadMethod(dBusValue.InnerDBusTypes![0])))))
+ : TupleExpression()
+ .AddArguments(
+ dBusValue.InnerDBusTypes!.Select(innerDBusValue => Argument(
+ InvocationExpression(
+ MakeMemberAccessExpression("reader", GetOrAddReadMethod(innerDBusValue)))))
+ .ToArray())))));
return identifier;
}
@@ -367,7 +280,7 @@ namespace Tmds.DBus.SourceGenerator
BlockSyntax block = Block()
.AddStatements(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("Reader"))
+ VariableDeclaration(IdentifierName("Reader"))
.AddVariables(
VariableDeclarator("reader")
.WithInitializer(
@@ -398,7 +311,7 @@ namespace Tmds.DBus.SourceGenerator
{
block = block.AddStatements(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName(dBusValues[i].DotNetType))
+ VariableDeclaration(GetDotnetType(dBusValues[i], AccessMode.Read))
.AddVariables(
VariableDeclarator($"arg{i}")
.WithInitializer(
@@ -415,11 +328,13 @@ namespace Tmds.DBus.SourceGenerator
}
_readMethodExtensions.Add(identifier,
- MethodDeclaration(ParseTypeName(ParseReturnType(dBusValues)!), identifier)
+ MethodDeclaration(ParseReturnType(dBusValues, AccessMode.Read)!, identifier)
.AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
- Parameter(Identifier("message")).WithType(ParseTypeName("Message")),
- Parameter(Identifier("_")).WithType(NullableType(PredefinedType(Token(SyntaxKind.ObjectKeyword)))))
+ Parameter(Identifier("message"))
+ .WithType(IdentifierName("Message")),
+ Parameter(Identifier("_"))
+ .WithType(NullableType(PredefinedType(Token(SyntaxKind.ObjectKeyword)))))
.WithBody(block));
return identifier;
@@ -432,19 +347,23 @@ namespace Tmds.DBus.SourceGenerator
return identifier;
_writeMethodExtensions.Add(identifier,
- MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), identifier)
- .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
+ MethodDeclaration(
+ PredefinedType(Token(SyntaxKind.VoidKeyword)), identifier)
+ .AddModifiers(
+ Token(SyntaxKind.PublicKeyword),
+ Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
Parameter(Identifier("writer"))
- .WithType(ParseTypeName("MessageWriter"))
+ .WithType(IdentifierName("MessageWriter"))
.AddModifiers(Token(SyntaxKind.ThisKeyword), Token(SyntaxKind.RefKeyword)),
Parameter(Identifier("values"))
- .WithType(ParseTypeName(dBusValue.DotNetType)))
+ .WithType(
+ GetDotnetType(dBusValue, AccessMode.Write, true)))
.WithBody(
Block()
.AddStatements(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("ArrayStart"))
+ VariableDeclaration(IdentifierName("ArrayStart"))
.AddVariables(
VariableDeclarator("arrayStart")
.WithInitializer(
@@ -454,11 +373,21 @@ namespace Tmds.DBus.SourceGenerator
.AddArgumentListArguments(
Argument(
MakeMemberAccessExpression("DBusType", Enum.GetName(typeof(DBusType), dBusValue.InnerDBusTypes![0].DBusType)!))))))),
- ForEachStatement(ParseTypeName(dBusValue.InnerDBusTypes[0].DotNetType), "value", IdentifierName("values"), ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("writer", GetOrAddWriteMethod(dBusValue.InnerDBusTypes[0])))
- .AddArgumentListArguments(
- Argument(IdentifierName("value"))))),
+ IfStatement(
+ IsPatternExpression(
+ IdentifierName("values"),
+ UnaryPattern(
+ ConstantPattern(
+ LiteralExpression(SyntaxKind.NullLiteralExpression)))),
+ ForEachStatement(
+ GetDotnetType(dBusValue.InnerDBusTypes[0], AccessMode.Write, true),
+ "value",
+ IdentifierName("values"),
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", GetOrAddWriteMethod(dBusValue.InnerDBusTypes[0])))
+ .AddArgumentListArguments(
+ Argument(IdentifierName("value")))))),
ExpressionStatement(
InvocationExpression(
MakeMemberAccessExpression("writer", "WriteArrayEnd"))
@@ -476,18 +405,26 @@ namespace Tmds.DBus.SourceGenerator
_writeMethodExtensions.Add(identifier,
MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), identifier)
- .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
+ .AddModifiers(
+ Token(SyntaxKind.PublicKeyword),
+ Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
- Parameter(Identifier("writer"))
- .WithType(ParseTypeName("MessageWriter"))
- .AddModifiers(Token(SyntaxKind.ThisKeyword), Token(SyntaxKind.RefKeyword)),
- Parameter(Identifier("values"))
- .WithType(ParseTypeName(dBusValue.DotNetType)))
+ Parameter(
+ Identifier("writer"))
+ .WithType(
+ IdentifierName("MessageWriter"))
+ .AddModifiers(
+ Token(SyntaxKind.ThisKeyword),
+ Token(SyntaxKind.RefKeyword)),
+ Parameter(
+ Identifier("values"))
+ .WithType(
+ GetDotnetType(dBusValue, AccessMode.Write, true)))
.WithBody(
Block()
.AddStatements(
LocalDeclarationStatement(
- VariableDeclaration(ParseTypeName("ArrayStart"))
+ VariableDeclaration(IdentifierName("ArrayStart"))
.AddVariables(
VariableDeclarator("arrayStart")
.WithInitializer(
@@ -497,26 +434,41 @@ namespace Tmds.DBus.SourceGenerator
.AddArgumentListArguments(
Argument(
MakeMemberAccessExpression("DBusType", "Struct"))))))),
- ForEachStatement(ParseTypeName($"KeyValuePair<{dBusValue.InnerDotNetTypes![0]}, {dBusValue.InnerDotNetTypes![1]}>"), "value", IdentifierName("values"), Block(
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("writer", "WriteStructureStart"))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("writer", GetOrAddWriteMethod(dBusValue.InnerDBusTypes![0])))
- .AddArgumentListArguments(
- Argument(MakeMemberAccessExpression("value", "Key")))),
- ExpressionStatement(
- InvocationExpression(
- MakeMemberAccessExpression("writer", GetOrAddWriteMethod(dBusValue.InnerDBusTypes![1])))
- .AddArgumentListArguments(
- Argument(MakeMemberAccessExpression("value", "Value"))))
- )),
+ IfStatement(
+ IsPatternExpression(
+ IdentifierName("values"),
+ UnaryPattern(
+ ConstantPattern(
+ LiteralExpression(SyntaxKind.NullLiteralExpression)))),
+ ForEachStatement(
+ GenericName("KeyValuePair")
+ .AddTypeArgumentListArguments(
+ GetDotnetType(dBusValue.InnerDBusTypes![0], AccessMode.Write),
+ GetDotnetType(dBusValue.InnerDBusTypes![1], AccessMode.Write, true)),
+ "value",
+ IdentifierName("values"),
+ Block(
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", "WriteStructureStart"))),
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", GetOrAddWriteMethod(dBusValue.InnerDBusTypes![0])))
+ .AddArgumentListArguments(
+ Argument(
+ MakeMemberAccessExpression("value", "Key")))),
+ ExpressionStatement(
+ InvocationExpression(
+ MakeMemberAccessExpression("writer", GetOrAddWriteMethod(dBusValue.InnerDBusTypes![1])))
+ .AddArgumentListArguments(
+ Argument(
+ MakeMemberAccessExpression("value", "Value"))))))),
ExpressionStatement(
InvocationExpression(
MakeMemberAccessExpression("writer", "WriteArrayEnd"))
.AddArgumentListArguments(
- Argument(IdentifierName("arrayStart")))))));
+ Argument(
+ IdentifierName("arrayStart")))))));
return identifier;
}
@@ -532,10 +484,10 @@ namespace Tmds.DBus.SourceGenerator
.AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
Parameter(Identifier("writer"))
- .WithType(ParseTypeName("MessageWriter"))
+ .WithType(IdentifierName("MessageWriter"))
.AddModifiers(Token(SyntaxKind.ThisKeyword), Token(SyntaxKind.RefKeyword)),
Parameter(Identifier("value"))
- .WithType(ParseTypeName(dBusValue.DotNetType)))
+ .WithType(GetDotnetType(dBusValue, AccessMode.Write, true)))
.WithBody(
Block(
ExpressionStatement(
diff --git a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.cs b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.cs
index 821cda7e69..aa47701150 100644
--- a/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.cs
+++ b/src/Linux/Tmds.DBus.SourceGenerator/DBusSourceGenerator.cs
@@ -59,7 +59,9 @@ namespace Tmds.DBus.SourceGenerator
foreach (DBusInterface dBusInterface in value.Node.Interfaces!)
{
TypeDeclarationSyntax typeDeclarationSyntax = GenerateProxy(dBusInterface);
- NamespaceDeclarationSyntax namespaceDeclaration = NamespaceDeclaration(IdentifierName("Tmds.DBus.SourceGenerator")).AddMembers(typeDeclarationSyntax);
+ NamespaceDeclarationSyntax namespaceDeclaration = NamespaceDeclaration(
+ IdentifierName("Tmds.DBus.SourceGenerator"))
+ .AddMembers(typeDeclarationSyntax);
CompilationUnitSyntax compilationUnit = MakeCompilationUnit(namespaceDeclaration);
productionContext.AddSource($"Tmds.DBus.SourceGenerator.{Pascalize(dBusInterface.Name!)}.g.cs", compilationUnit.GetText(Encoding.UTF8));
}
@@ -68,7 +70,9 @@ namespace Tmds.DBus.SourceGenerator
foreach (DBusInterface dBusInterface in value.Node.Interfaces!)
{
TypeDeclarationSyntax typeDeclarationSyntax = GenerateHandler(dBusInterface);
- NamespaceDeclarationSyntax namespaceDeclaration = NamespaceDeclaration(IdentifierName("Tmds.DBus.SourceGenerator")).AddMembers(typeDeclarationSyntax);
+ NamespaceDeclarationSyntax namespaceDeclaration = NamespaceDeclaration(
+ IdentifierName("Tmds.DBus.SourceGenerator"))
+ .AddMembers(typeDeclarationSyntax);
CompilationUnitSyntax compilationUnit = MakeCompilationUnit(namespaceDeclaration);
productionContext.AddSource($"Tmds.DBus.SourceGenerator.{Pascalize(dBusInterface.Name!)}.g.cs", compilationUnit.GetText(Encoding.UTF8));
}
@@ -76,25 +80,32 @@ namespace Tmds.DBus.SourceGenerator
}
}
- CompilationUnitSyntax readerExtensions = MakeCompilationUnit(NamespaceDeclaration(IdentifierName("Tmds.DBus.SourceGenerator"))
+ CompilationUnitSyntax readerExtensions = MakeCompilationUnit(
+ NamespaceDeclaration(
+ IdentifierName("Tmds.DBus.SourceGenerator"))
.AddMembers(
ClassDeclaration("ReaderExtensions")
.AddModifiers(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.StaticKeyword))
.WithMembers(
List(_readMethodExtensions.Values))));
- CompilationUnitSyntax writerExtensions = MakeCompilationUnit(NamespaceDeclaration(IdentifierName("Tmds.DBus.SourceGenerator"))
+ CompilationUnitSyntax writerExtensions = MakeCompilationUnit(
+ NamespaceDeclaration(
+ IdentifierName("Tmds.DBus.SourceGenerator"))
.AddMembers(
ClassDeclaration("WriterExtensions")
.AddModifiers(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.StaticKeyword))
.WithMembers(
- List(_writeMethodExtensions.Values))));
+ List(_writeMethodExtensions.Values)
+ .Add(MakeWriteNullableStringMethod())
+ .Add(MakeWriteObjectPathSafeMethod()))));
- productionContext.AddSource("Tmds.DBus.SourceGenerator.PropertyChanges.cs", MakePropertyChangesClass().GetText(Encoding.UTF8));
- productionContext.AddSource("Tmds.DBus.SourceGenerator.SignalHelper.cs", MakeSignalHelperClass().GetText(Encoding.UTF8));
+ productionContext.AddSource("Tmds.DBus.SourceGenerator.PropertyChanges.cs", PropertyChangesClass);
+ productionContext.AddSource("Tmds.DBus.SourceGenerator.SignalHelper.cs", SignalHelperClass);
+ productionContext.AddSource("Tmds.DBus.SourceGenerator.PathHandler.cs", PathHandlerClass);
+ productionContext.AddSource("Tmds.DBus.SourceGenerator.IDBusInterfaceHandler.cs", DBusInterfaceHandlerInterface);
productionContext.AddSource("Tmds.DBus.SourceGenerator.ReaderExtensions.cs", readerExtensions.GetText(Encoding.UTF8));
productionContext.AddSource("Tmds.DBus.SourceGenerator.WriterExtensions.cs", writerExtensions.GetText(Encoding.UTF8));
- productionContext.AddSource("Tmds.DBus.SourceGenerator.VariantExtensions.cs", VariantExtensions);
});
}
}
diff --git a/src/Linux/Tmds.DBus.SourceGenerator/SignatureReader.cs b/src/Linux/Tmds.DBus.SourceGenerator/SignatureReader.cs
index 25332c8870..8225897391 100644
--- a/src/Linux/Tmds.DBus.SourceGenerator/SignatureReader.cs
+++ b/src/Linux/Tmds.DBus.SourceGenerator/SignatureReader.cs
@@ -28,16 +28,12 @@ namespace Tmds.DBus.SourceGenerator
if (length > 1)
{
- switch (type)
+ innerSignature = type switch
{
- case DBusType.Array:
- innerSignature = _signature.Slice(1, length - 1);
- break;
- case DBusType.Struct:
- case DBusType.DictEntry:
- innerSignature = _signature.Slice(1, length - 2);
- break;
- }
+ DBusType.Array => _signature.Slice(1, length - 1),
+ DBusType.Struct or DBusType.DictEntry => _signature.Slice(1, length - 2),
+ _ => innerSignature
+ };
}
_signature = _signature.Slice(length);
@@ -158,12 +154,12 @@ namespace Tmds.DBus.SourceGenerator
signature = signature.Slice(1);
T keyType = Transform(keySignature, map);
T valueType = Transform(valueSignature, map);
- return map(DBusType.DictEntry, new[] { keyType, valueType });
+ return map(DBusType.DictEntry, [keyType, valueType]);
case DBusType.Array:
signature = signature.Slice(1);
T elementType = Transform(signature, map);
//signature = signature.Slice(1);
- return map(DBusType.Array, new[] { elementType });
+ return map(DBusType.Array, [elementType]);
case DBusType.Struct:
signature = signature.Slice(1, signature.Length - 2);
int typeCount = CountTypes(signature);
@@ -176,7 +172,7 @@ namespace Tmds.DBus.SourceGenerator
return map(DBusType.Struct, innerTypes);
default:
- return map(dbusType, Array.Empty());
+ return map(dbusType, []);
}
}
diff --git a/src/Linux/Tmds.DBus.SourceGenerator/Tmds.DBus.SourceGenerator.csproj b/src/Linux/Tmds.DBus.SourceGenerator/Tmds.DBus.SourceGenerator.csproj
index d54309985c..8aa357fba1 100644
--- a/src/Linux/Tmds.DBus.SourceGenerator/Tmds.DBus.SourceGenerator.csproj
+++ b/src/Linux/Tmds.DBus.SourceGenerator/Tmds.DBus.SourceGenerator.csproj
@@ -9,5 +9,13 @@
+
+
+
+
+
+
+
+
diff --git a/src/Linux/Tmds.DBus/Address.cs b/src/Linux/Tmds.DBus/Address.cs
deleted file mode 100644
index 8125bdf1f8..0000000000
--- a/src/Linux/Tmds.DBus/Address.cs
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2006 Alp Toker
-// Copyright 2016 Tom Deseyn
-// This software is made available under the MIT License
-// See COPYING for details
-
-using System;
-using System.IO.MemoryMappedFiles;
-using System.Runtime.InteropServices;
-#if NET6_0_OR_GREATER
-using System.Runtime.Versioning;
-#endif
-
-namespace Tmds.DBus
-{
- ///
- /// Helper class for determining D-Bus addresses.
- ///
- public static class Address
- {
- private static bool _systemAddressResolved = false;
- private static string _systemAddress = null;
- private static bool _sessionAddressResolved = false;
- private static string _sessionAddress = null;
-
- ///
- /// Address of System bus.
- ///
- public static string System
- {
- get
- {
- if (_systemAddressResolved)
- {
- return _systemAddress;
- }
-
- _systemAddress = GetEnvironmentVariable("DBUS_SYSTEM_BUS_ADDRESS");
- if (String.IsNullOrEmpty(_systemAddress) && !Environment.IsWindows)
- _systemAddress = "unix:path=/var/run/dbus/system_bus_socket";
-
- _systemAddressResolved = true;
- return _systemAddress;
- }
- }
-
- ///
- /// Address of Session bus.
- ///
- public static string Session
- {
- get
- {
- if (_sessionAddressResolved)
- {
- return _sessionAddress;
- }
- _sessionAddress = GetEnvironmentVariable("DBUS_SESSION_BUS_ADDRESS");
-
- if (string.IsNullOrEmpty(_sessionAddress))
- {
- if (Environment.IsWindows)
- {
- _sessionAddress = GetSessionBusAddressFromSharedMemory();
- }
- else
- {
- _sessionAddress = GetSessionBusAddressFromX11();
- }
- }
- _sessionAddressResolved = true;
- return _sessionAddress;
- }
- }
-
- private static string GetEnvironmentVariable(string name)
- {
- return global::System.Environment.GetEnvironmentVariable(name);
- }
-
- private static string GetSessionBusAddressFromX11()
- {
- if (!string.IsNullOrEmpty(GetEnvironmentVariable("DISPLAY")))
- {
- var display = Interop.XOpenDisplay(null);
- if (display == IntPtr.Zero)
- {
- return null;
- }
- string username;
- unsafe
- {
- const int BufLen = 1024;
- byte* stackBuf = stackalloc byte[BufLen];
- Interop.Passwd passwd;
- IntPtr result;
- Interop.getpwuid_r(Interop.getuid(), out passwd, stackBuf, BufLen, out result);
- if (result != IntPtr.Zero)
- {
- username = Marshal.PtrToStringAnsi(passwd.Name);
- }
- else
- {
- return null;
- }
- }
- var machineId = Environment.MachineId.Replace("-", string.Empty);
- var selectionName = $"_DBUS_SESSION_BUS_SELECTION_{username}_{machineId}";
- var selectionAtom = Interop.XInternAtom(display, selectionName, false);
- if (selectionAtom == IntPtr.Zero)
- {
- return null;
- }
- var owner = Interop.XGetSelectionOwner(display, selectionAtom);
- if (owner == IntPtr.Zero)
- {
- return null;
- }
- var addressAtom = Interop.XInternAtom(display, "_DBUS_SESSION_BUS_ADDRESS", false);
- if (addressAtom == IntPtr.Zero)
- {
- return null;
- }
-
- IntPtr actualReturnType;
- IntPtr actualReturnFormat;
- IntPtr nrItemsReturned;
- IntPtr bytesAfterReturn;
- IntPtr propReturn;
- int rv = Interop.XGetWindowProperty(display, owner, addressAtom, 0, 1024, false, (IntPtr)31 /* XA_STRING */,
- out actualReturnType, out actualReturnFormat, out nrItemsReturned, out bytesAfterReturn, out propReturn);
- string address = rv == 0 ? Marshal.PtrToStringAnsi(propReturn) : null;
- if (propReturn != IntPtr.Zero)
- {
- Interop.XFree(propReturn);
- }
-
- Interop.XCloseDisplay(display);
-
- return address;
- }
- else
- {
- return null;
- }
- }
-
-#if NET6_0_OR_GREATER
- [SupportedOSPlatform("windows")]
-#endif
- private static string GetSessionBusAddressFromSharedMemory()
- {
- string result = ReadSharedMemoryString("DBusDaemonAddressInfo", 255);
- if (String.IsNullOrEmpty(result))
- result = ReadSharedMemoryString("DBusDaemonAddressInfoDebug", 255); // a DEBUG build of the daemon uses this different address...
- return result;
- }
-
-#if NET6_0_OR_GREATER
- [SupportedOSPlatform("windows")]
-#endif
- private static string ReadSharedMemoryString(string id, long maxlen = -1)
- {
- MemoryMappedFile shmem;
- try
- {
- shmem = MemoryMappedFile.OpenExisting(id);
- }
- catch
- {
- shmem = null;
- }
- if (shmem == null)
- return null;
- MemoryMappedViewStream s = shmem.CreateViewStream();
- long len = s.Length;
- if (maxlen >= 0 && len > maxlen)
- len = maxlen;
- if (len == 0)
- return string.Empty;
- if (len > Int32.MaxValue)
- len = Int32.MaxValue;
- byte[] bytes = new byte[len];
- int count = s.Read(bytes, 0, (int)len);
- if (count <= 0)
- return string.Empty;
-
- count = 0;
- while (count < len && bytes[count] != 0)
- count++;
-
- return global::System.Text.Encoding.UTF8.GetString(bytes, 0, count);
- }
- }
-}
diff --git a/src/Linux/Tmds.DBus/AddressEntry.cs b/src/Linux/Tmds.DBus/AddressEntry.cs
deleted file mode 100644
index 372dda7c16..0000000000
--- a/src/Linux/Tmds.DBus/AddressEntry.cs
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright 2006 Alp Toker
-// Copyright 2010 Alan McGovern
-// Copyright 2016 Tom Deseyn
-// This software is made available under the MIT License
-// See COPYING for details
-
-using System;
-using System.Net;
-using System.Text;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Tmds.DBus.Transports;
-
-namespace Tmds.DBus
-{
- internal class AddressEntry
- {
- public static AddressEntry[] ParseEntries(string addresses)
- {
- if (addresses == null)
- throw new ArgumentNullException(nameof(addresses));
-
- List entries = new List();
-
- foreach (string entryStr in addresses.Split(';'))
- entries.Add(AddressEntry.Parse(entryStr));
-
- return entries.ToArray();
- }
-
- public string Method;
- public readonly IDictionary Properties = new Dictionary();
- public Guid Guid = Guid.Empty;
-
- public override string ToString()
- {
- StringBuilder sb = new StringBuilder();
- sb.Append(Method);
- sb.Append(':');
-
- bool first = true;
- foreach (KeyValuePair prop in Properties)
- {
- if (first)
- first = false;
- else
- sb.Append(',');
-
- sb.Append(prop.Key);
- sb.Append('=');
- sb.Append(Escape(prop.Value));
- }
-
- if (Guid != Guid.Empty)
- {
- if (Properties.Count != 0)
- sb.Append(',');
- sb.Append("guid");
- sb.Append('=');
- sb.Append(Guid.ToString("N"));
- }
-
- return sb.ToString();
- }
-
- static string Escape(string str)
- {
- if (str == null)
- return String.Empty;
-
- StringBuilder sb = new StringBuilder();
- int len = str.Length;
-
- for (int i = 0; i != len; i++)
- {
- char c = str[i];
-
- //everything other than the optionally escaped chars _must_ be escaped
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
- || c == '-' || c == '_' || c == '/' || c == '\\' || c == '.')
- sb.Append(c);
- else
- sb.Append(HexEscape(c));
- }
-
- return sb.ToString();
- }
-
- static string Unescape(string str)
- {
- if (str == null)
- return String.Empty;
-
- StringBuilder sb = new StringBuilder();
- int len = str.Length;
- int i = 0;
- while (i != len)
- {
- if (IsHexEncoding(str, i))
- sb.Append(HexUnescape(str, ref i));
- else
- sb.Append(str[i++]);
- }
-
- return sb.ToString();
- }
-
- public static string HexEscape(char character)
- {
- if (character > '\xff')
- {
- throw new ArgumentOutOfRangeException("character");
- }
- char[] chars = new char[3];
- int pos = 0;
- EscapeAsciiChar(character, chars, ref pos);
- return new string(chars);
- }
-
- private const char c_DummyChar = (char)0xFFFF;
- private static readonly char[] s_hexUpperChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
-
- internal static void EscapeAsciiChar(char ch, char[] to, ref int pos)
- {
- to[pos++] = '%';
- to[pos++] = s_hexUpperChars[(ch & 0xf0) >> 4];
- to[pos++] = s_hexUpperChars[ch & 0xf];
- }
-
-
- public static char HexUnescape(string pattern, ref int index)
- {
- if ((index < 0) || (index >= pattern.Length))
- {
- throw new ArgumentOutOfRangeException("index");
- }
- if ((pattern[index] == '%')
- && (pattern.Length - index >= 3))
- {
- char ret = EscapedAscii(pattern[index + 1], pattern[index + 2]);
- if (ret != c_DummyChar)
- {
- index += 3;
- return ret;
- }
- }
- return pattern[index++];
- }
- public static bool IsHexEncoding(string pattern, int index)
- {
- if ((pattern.Length - index) < 3)
- {
- return false;
- }
- if ((pattern[index] == '%') && EscapedAscii(pattern[index + 1], pattern[index + 2]) != c_DummyChar)
- {
- return true;
- }
- return false;
- }
-
- private static char EscapedAscii(char digit, char next)
- {
- if (!(((digit >= '0') && (digit <= '9'))
- || ((digit >= 'A') && (digit <= 'F'))
- || ((digit >= 'a') && (digit <= 'f'))))
- {
- return c_DummyChar;
- }
-
- int res = (digit <= '9')
- ? ((int)digit - (int)'0')
- : (((digit <= 'F')
- ? ((int)digit - (int)'A')
- : ((int)digit - (int)'a'))
- + 10);
-
- if (!(((next >= '0') && (next <= '9'))
- || ((next >= 'A') && (next <= 'F'))
- || ((next >= 'a') && (next <= 'f'))))
- {
- return c_DummyChar;
- }
-
- return (char)((res << 4) + ((next <= '9')
- ? ((int)next - (int)'0')
- : (((next <= 'F')
- ? ((int)next - (int)'A')
- : ((int)next - (int)'a'))
- + 10)));
- }
-
-
- public static AddressEntry Parse(string s)
- {
- AddressEntry entry = new AddressEntry();
-
- string[] parts = s.Split(new[] { ':' }, 2);
-
- if (parts.Length < 2)
- throw new FormatException("No colon found");
-
- entry.Method = parts[0];
-
- if (parts[1].Length > 0)
- {
- foreach (string propStr in parts[1].Split(','))
- {
- parts = propStr.Split('=');
-
- if (parts.Length < 2)
- throw new FormatException("No equals sign found");
- if (parts.Length > 2)
- throw new FormatException("Too many equals signs found");
-
- if (parts[0] == "guid")
- {
- try
- {
- entry.Guid = Guid.ParseExact(parts[1], "N");
- }
- catch
- {
- throw new FormatException("Invalid guid specified");
- }
- continue;
- }
-
- entry.Properties[parts[0]] = Unescape(parts[1]);
- }
- }
-
- return entry;
- }
-
- public async Task ResolveAsync(bool listen = false)
- {
- switch (Method)
- {
- case "tcp":
- {
- string host, portStr, family;
- int port = 0;
-
- if (!Properties.TryGetValue ("host", out host))
- host = "localhost";
-
- if (!Properties.TryGetValue ("port", out portStr) && !listen)
- throw new FormatException ("No port specified");
-
- if (portStr != null && !Int32.TryParse (portStr, out port))
- throw new FormatException("Invalid port: \"" + port + "\"");
-
- if (!Properties.TryGetValue ("family", out family))
- family = null;
-
- if (string.IsNullOrEmpty(host))
- {
- throw new ArgumentException("host");
- }
-
- IPAddress[] addresses = await Dns.GetHostAddressesAsync(host).ConfigureAwait(false);
-
- var endpoints = new IPEndPoint[addresses.Length];
- for (int i = 0; i < endpoints.Length; i++)
- {
- endpoints[i] = new IPEndPoint(addresses[i], port);
- }
- return endpoints;
- }
- case "unix":
- {
- string path;
- bool abstr;
-
- if (Properties.TryGetValue("path", out path))
- abstr = false;
- else if (Properties.TryGetValue("abstract", out path))
- abstr = true;
- else
- throw new ArgumentException("No path specified for UNIX transport");
-
- if (String.IsNullOrEmpty(path))
- {
- throw new ArgumentException("path");
- }
-
- if (abstr)
- {
- path = (char)'\0' + path;
- }
-
- return new EndPoint[] { new UnixDomainSocketEndPoint(path) };
- }
- default:
- throw new NotSupportedException("Transport method \"" + Method + "\" not supported");
- }
- }
- }
-}
diff --git a/src/Linux/Tmds.DBus/ArgumentAttribute.cs b/src/Linux/Tmds.DBus/ArgumentAttribute.cs
deleted file mode 100644
index 15a08d1892..0000000000
--- a/src/Linux/Tmds.DBus/ArgumentAttribute.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2016 Tom Deseyn
-// This software is made available under the MIT License
-// See COPYING for details
-
-using System;
-
-namespace Tmds.DBus
-{
- ///
- /// Indicates the method return type or signal type represents a single D-Bus argument.
- ///
- [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = true)]
- public sealed class ArgumentAttribute : Attribute
- {
- ///
- /// Name of the argument.
- ///
- public string Name { get; }
-
- ///
- /// Creates an instance of the ArgumentAttribute with the specified name.
- ///
- /// Name of the argument.
- public ArgumentAttribute(string name)
- {
- Name = name;
- }
-
- ///
- /// Creates an instance of the ArgumentAttribute.
- ///
- public ArgumentAttribute()
- {
- Name = "value";
- }
- }
-}
diff --git a/src/Linux/Tmds.DBus/ClientConnectionOptions.cs b/src/Linux/Tmds.DBus/ClientConnectionOptions.cs
deleted file mode 100644
index 3a9221daa2..0000000000
--- a/src/Linux/Tmds.DBus/ClientConnectionOptions.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2017 Tom Deseyn
-// This software is made available under the MIT License
-// See COPYING for details
-
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Tmds.DBus
-{
- ///
- /// Options that configure the behavior of a Connection to a remote peer.
- ///
- public class ClientConnectionOptions : ConnectionOptions
- {
- private string _address;
-
- ///
- /// Creates a new Connection with a specific address.
- ///
- /// Address of the D-Bus peer.
- public ClientConnectionOptions(string address)
- {
- if (address == null)
- throw new ArgumentNullException(nameof(address));
- _address = address;
- }
-
- ///
- /// Base constructor for derived types.
- ///
- protected ClientConnectionOptions()
- {}
-
- ///
- /// Automatically connect and re-connect the Connection.
- ///
- public bool AutoConnect { get; set; }
-
- ///
- /// Sets up tunnel/connects to the remote peer.
- ///
- protected internal virtual Task SetupAsync()
- {
- return Task.FromResult(
- new ClientSetupResult
- {
- ConnectionAddress = _address,
- SupportsFdPassing = true,
- UserId = Environment.UserId
- });
- }
-
- ///
- /// Action to clean up resources created during succesfull execution of SetupAsync.
- ///
- protected internal virtual void Teardown(object token)
- {}
-
- ///
- /// Run Task continuations asynchronously.
- ///
- public bool RunContinuationsAsynchronously { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/Linux/Tmds.DBus/ClientSetupResult.cs b/src/Linux/Tmds.DBus/ClientSetupResult.cs
deleted file mode 100644
index 9713d1c2bf..0000000000
--- a/src/Linux/Tmds.DBus/ClientSetupResult.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2017 Tom Deseyn
-// This software is made available under the MIT License
-// See COPYING for details
-
-using System;
-using System.Threading;
-
-namespace Tmds.DBus
-{
- ///
- /// Result of ClientConnectionOptions.SetupAsync
- ///
- public class ClientSetupResult
- {
- ///
- /// Address of the D-Bus peer.
- ///
- public string ConnectionAddress { get; set; }
-
- ///
- /// Object passed to ConnectionOptions.Teardown.
- ///
- public object TeardownToken { get; set; }
-
- ///
- /// Authentication User ID (Linux UID).
- ///
- public string UserId { get; set; }
-
- ///
- /// Indicates whether the connection supports Fd passing.
- ///
- public bool SupportsFdPassing { get; set; }
- }
-}
\ No newline at end of file
diff --git a/src/Linux/Tmds.DBus/CloseSafeHandle.cs b/src/Linux/Tmds.DBus/CloseSafeHandle.cs
deleted file mode 100644
index 708da25d8e..0000000000
--- a/src/Linux/Tmds.DBus/CloseSafeHandle.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2017 Tom Deseyn
-// This software is made available under the MIT License
-// See COPYING for details
-
-using System;
-using System.Runtime.InteropServices;
-
-namespace Tmds.DBus
-{
- ///
- /// Generic file descriptor SafeHandle.
- ///
- public class CloseSafeHandle : SafeHandle
- {
- ///
- /// Creates a new CloseSafeHandle.
- ///
- /// An IntPtr object that represents the pre-existing handle to use.
- /// true to reliably release the handle during the finalization phase; false to prevent reliable release.
- public CloseSafeHandle(IntPtr preexistingHandle, bool ownsHandle)
- : base(new IntPtr(-1), ownsHandle)
- {
- SetHandle(preexistingHandle);
- }
-
- ///
- /// Gets a value that indicates whether the handle is invalid.
- ///
- public override bool IsInvalid
- {
- get { return handle == new IntPtr(-1); }
- }
-
- ///
- /// When overridden in a derived class, executes the code required to free the handle.
- ///
- protected override bool ReleaseHandle()
- {
- return close(handle.ToInt32()) == 0;
- }
-
- [DllImport("libc", SetLastError = true)]
- internal static extern int close(int fd);
- }
-}
\ No newline at end of file
diff --git a/src/Linux/Tmds.DBus/CodeGen/ArgTypeInspector.cs b/src/Linux/Tmds.DBus/CodeGen/ArgTypeInspector.cs
deleted file mode 100644
index 97b3e1d80b..0000000000
--- a/src/Linux/Tmds.DBus/CodeGen/ArgTypeInspector.cs
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright 2016 Tom Deseyn
-// This software is made available under the MIT License
-// See COPYING for details
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-namespace Tmds.DBus.CodeGen
-{
- static internal class ArgTypeInspector
- {
- private static readonly Type s_idbusObjectType = typeof(IDBusObject);
- private static readonly Type s_idictionaryGenericType = typeof(IDictionary<,>);
- private static readonly Type s_keyValueGenericPairType = typeof(KeyValuePair<,>);
- private static readonly Type s_ienumerableGenricType = typeof(IEnumerable<>);
- private static readonly Type s_ienumerableType = typeof(System.Collections.IEnumerable);
- private static readonly Type s_objectType = typeof(Object);
- private static readonly Type s_valueType = typeof(ValueType);
- private static readonly Type s_ilistGenricType = typeof(IList<>);
- private static readonly Type s_icollectionGenricType = typeof(ICollection<>);
- private static readonly Type s_stringObjectKeyValuePairType = typeof(KeyValuePair);
- private static readonly Type[] s_valueTupleTypes = new [] {
- typeof(ValueTuple<>),
- typeof(ValueTuple<,>),
- typeof(ValueTuple<,,>),
- typeof(ValueTuple<,,,>),
- typeof(ValueTuple<,,,,>),
- typeof(ValueTuple<,,,,,>),
- typeof(ValueTuple<,,,,,,>),
- typeof(ValueTuple<,,,,,,,>)
- };
- private static readonly IComparer s_valueTupleFieldComparer = new StructFieldInfoComparer(true);
- private static readonly IComparer s_otherFieldComparer = new StructFieldInfoComparer(false);
-
- public static bool IsDBusObjectType(Type type, bool isCompileTimeType)
- {
- if (type == s_idbusObjectType)
- {
- return true;
- }
- var typeInfo = type.GetTypeInfo();
- if (isCompileTimeType)
- {
- return typeInfo.IsInterface && typeInfo.ImplementedInterfaces.Contains(s_idbusObjectType);
- }
- else
- {
- return typeInfo.ImplementedInterfaces.Contains(s_idbusObjectType);
- }
- }
-
- public static bool IsSafeHandleType(Type type)
- {
- return type.GetTypeInfo().IsSubclassOf(typeof(SafeHandle));
- }
-
- public enum EnumerableType
- {
- NotEnumerable,
- Enumerable, // IEnumerable
- EnumerableKeyValuePair, // IEnumerable
- GenericDictionary, // IDictionary
- AttributeDictionary // AttributeDictionary
- }
-
- public static EnumerableType InspectEnumerableType(Type type, out Type elementType, bool isCompileTimeType)
- {
- elementType = null;
- var typeInfo = type.GetTypeInfo();
-
- if (isCompileTimeType)
- {
- if (typeInfo.IsArray)
- {
- elementType = typeInfo.GetElementType();
- return InspectElementType(elementType);
- }
- if (typeInfo.IsInterface && typeInfo.IsGenericType)
- {
- var genericTypeDefinition = typeInfo.GetGenericTypeDefinition();
- if (genericTypeDefinition == s_idictionaryGenericType)
- {
- elementType = s_keyValueGenericPairType.MakeGenericType(typeInfo.GenericTypeArguments);
- return EnumerableType.GenericDictionary;
- }
- else if (genericTypeDefinition == s_ienumerableGenricType ||
- genericTypeDefinition == s_ilistGenricType ||
- genericTypeDefinition == s_icollectionGenricType)
- {
- elementType = typeInfo.GenericTypeArguments[0];
- return InspectElementType(elementType);
- }
- else
- {
- return EnumerableType.NotEnumerable;
- }
- }
- var dictionaryAttribute = typeInfo.GetCustomAttribute(false);
- if (dictionaryAttribute != null)
- {
- elementType = s_stringObjectKeyValuePairType;
- return EnumerableType.AttributeDictionary;
- }
- return EnumerableType.NotEnumerable;
- }
- else
- {
- if (typeInfo.ImplementedInterfaces.Contains(s_idbusObjectType))
- {
- return EnumerableType.NotEnumerable;
- }
-
- var dictionaryAttribute = typeInfo.GetCustomAttribute(false);
- if (dictionaryAttribute != null)
- {
- elementType = s_stringObjectKeyValuePairType;
- return EnumerableType.AttributeDictionary;
- }
-
- if (!typeInfo.ImplementedInterfaces.Contains(s_ienumerableType))
- {
- return EnumerableType.NotEnumerable;
- }
-
- var enumerableTypes = from interf in typeInfo.ImplementedInterfaces
- let interfTypeinfo = interf.GetTypeInfo()
- where interfTypeinfo.IsGenericType && interfTypeinfo.GetGenericTypeDefinition() == s_ienumerableGenricType
- select interfTypeinfo;
-
- var enumerableCount = enumerableTypes.Count();
-
- if (enumerableCount == 1)
- {
- elementType = enumerableTypes.First().GenericTypeArguments[0];
- return InspectElementType(elementType);
- }
- else
- {
- throw new ArgumentException($"Cannot determine element type of enumerable type '$type.FullName'");
- }
- }
- }
-
- public static bool IsStructType(Type type)
- {
- bool isValueTuple;
- return IsStructType(type, out isValueTuple);
- }
-
- public static bool IsStructType(Type type, out bool isValueTuple)
- {
- isValueTuple = false;
- var typeInfo = type.GetTypeInfo();
- if (typeInfo.IsPointer ||
- typeInfo.IsInterface ||
- typeInfo.IsArray ||
- typeInfo.IsPrimitive ||
- typeInfo.IsAbstract)
- {
- return false;
- }
- if (IsValueTuple(typeInfo))
- {
- isValueTuple = true;
- return true;
- }
- else if (!typeInfo.IsLayoutSequential)
- {
- return false;
- }
-
- if (typeInfo.ImplementedInterfaces.Contains(s_idbusObjectType))
- {
- return false;
- }
-
- if (typeInfo.ImplementedInterfaces.Contains(s_ienumerableType))
- {
- return false;
- }
-
- if (typeInfo.BaseType != s_objectType &&
- typeInfo.BaseType != s_valueType)
- {
- return false;
- }
-
- var fields = type.GetFields (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- if (!fields.Any())
- {
- return false;
- }
-
- return true;
- }
-
- public static FieldInfo[] GetStructFields(Type structType, bool isValueTuple)
- {
- var fields = structType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- Array.Sort(fields, null, isValueTuple ? s_valueTupleFieldComparer : s_otherFieldComparer);
- return fields;
- }
-
- private static EnumerableType InspectElementType(Type elementType)
- {
- var typeInfo = elementType.GetTypeInfo();
- bool isKeyValuePair = typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == s_keyValueGenericPairType;
- if (isKeyValuePair)
- {
- return EnumerableType.EnumerableKeyValuePair;
- }
- else
- {
- return EnumerableType.Enumerable;
- }
- }
-
- private static bool IsValueTuple(TypeInfo typeInfo)
- {
- if (typeInfo.IsGenericType)
- {
- var genericTypeDefinition = typeInfo.GetGenericTypeDefinition();
- return s_valueTupleTypes.Contains(genericTypeDefinition);
- }
- else
- {
- return false;
- }
- }
-
- private class StructFieldInfoComparer : IComparer
- {
- private bool _isValueTypleComparer;
- public StructFieldInfoComparer(bool isValueTypleComparer)
- {
- _isValueTypleComparer = isValueTypleComparer;
- }
-
- public int Compare(FieldInfo x, FieldInfo y)
- {
- if (_isValueTypleComparer)
- {
- // ValueTuples are not layout sequentially
- // The fields are named Item[1-7], Rest
- if (x.Name.Length == 4)
- {
- return 1;
- }
- return x.Name[x.Name.Length - 1].CompareTo(y.Name[y.Name.Length - 1]);
- }
- else
- {
- return x.MetadataToken.CompareTo(y.MetadataToken);
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Linux/Tmds.DBus/CodeGen/ArgumentDescription.cs b/src/Linux/Tmds.DBus/CodeGen/ArgumentDescription.cs
deleted file mode 100644
index 0be399835f..0000000000
--- a/src/Linux/Tmds.DBus/CodeGen/ArgumentDescription.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2016 Tom Deseyn
-// This software is made available under the MIT License
-// See COPYING for details
-
-using System;
-using Tmds.DBus.Protocol;
-
-namespace Tmds.DBus.CodeGen
-{
- internal class ArgumentDescription
- {
- public ArgumentDescription(string name, Signature signature, Type type)
- {
- Name = name;
- Signature = signature;
- Type = type;
- }
-
- public string Name { get; }
- public Signature Signature { get; }
- public Type Type { get; }
- }
-}
\ No newline at end of file
diff --git a/src/Linux/Tmds.DBus/CodeGen/DBusAdapter.cs b/src/Linux/Tmds.DBus/CodeGen/DBusAdapter.cs
deleted file mode 100644
index 0f25ab34e0..0000000000
--- a/src/Linux/Tmds.DBus/CodeGen/DBusAdapter.cs
+++ /dev/null
@@ -1,310 +0,0 @@
-// Copyright 2016 Tom Deseyn
-// This software is made available under the MIT License
-// See COPYING for details
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Tmds.DBus.Protocol;
-
-namespace Tmds.DBus.CodeGen
-{
- internal class DBusAdapter
- {
- internal delegate Task MethodCallHandler(object o, Message methodCall, IProxyFactory factory);
-
- private enum State
- {
- Registering,
- Registered,
- Unregistered
- }
-
- private readonly object _gate = new object();
- private readonly DBusConnection _connection;
- private readonly IProxyFactory _factory;
- private readonly ObjectPath2 _objectPath2;
- private readonly SynchronizationContext _synchronizationContext;
- protected internal string _typeIntrospection;
- protected internal readonly Dictionary _methodHandlers;
- protected internal readonly object _object;
-
- private State _state;
- private List _signalWatchers;
-
- protected DBusAdapter(DBusConnection connection, ObjectPath2 objectPath2, object o, IProxyFactory factory, SynchronizationContext synchronizationContext)
- {
- _connection = connection;
- _objectPath2 = objectPath2;
- _object = o;
- _state = State.Registering;
- _factory = factory;
- _synchronizationContext = synchronizationContext;
- _methodHandlers = new Dictionary();
- _methodHandlers.Add(GetMethodLookupKey("org.freedesktop.DBus.Introspectable", "Introspect", null), HandleIntrospect);
- }
-
- public ObjectPath2 Path2 => _objectPath2;
-
- public void Unregister()
- {
- lock (_gate)
- {
- if (_state == State.Unregistered)
- {
- return;
- }
- _state = State.Unregistered;
- if (_signalWatchers != null)
- {
- foreach (var disposable in _signalWatchers)
- {
- disposable.Dispose();
- }
- _signalWatchers = null;
- }
- }
- }
-
- public void CompleteRegistration()
- {
- lock (_gate)
- {
- if (_state == State.Registering)
- {
- _state = State.Registered;
- }
- else if (_state == State.Unregistered)
- {
- throw new InvalidOperationException("The object has been unregistered");
- }
- else if (_state == State.Registered)
- {
- throw new InvalidOperationException("The object has already been registered");
- }
- }
- }
-
- public async Task WatchSignalsAsync()
- {
- var tasks = StartWatchingSignals();
- IEnumerable signalDisposables = null;
-
- try
- {
- await Task.WhenAll(tasks).ConfigureAwait(false);
- signalDisposables = tasks.Select(task => task.Result);
-
- if (signalDisposables.Contains(null))
- {
- throw new InvalidOperationException("One or more Watch-methods returned a null IDisposable");
- }
- }
- catch
- {
- foreach (var task in tasks)
- {
- try
- {
- var disposable = await task.ConfigureAwait(false);
- disposable?.Dispose();
- }
- finally
- { }
- }
- throw;
- }
-
- lock (_gate)
- {
- if (_state == State.Registering)
- {
- _signalWatchers = new List();
- _signalWatchers.AddRange(signalDisposables);
- }
- else if (_state == State.Unregistered)
- {
- foreach (var disposable in signalDisposables)
- {
- disposable.Dispose();
- }
- }
- }
- }
-
- static protected internal string GetMethodLookupKey(string iface, string member, Signature? signature)
- {
- return $"{iface}.{member}.{signature?.Value}";
- }
-
- static protected internal string GetPropertyLookupKey(string iface, string member, Signature? signature)
- {
- return $"org.freedesktop.DBus.Properties.{iface}.{member}.{signature?.Value}";
- }
-
- static protected internal string GetPropertyAddKey(string iface, string member, Signature? signature)
- {
- return $"org.freedesktop.DBus.Properties.{iface}.{member}.s{signature?.Value}";
- }
-
- public async Task HandleMethodCall(Message methodCall)
- {
- var key = GetMethodLookupKey(methodCall.Header.Interface, methodCall.Header.Member, methodCall.Header.Signature);
- MethodCallHandler handler = null;
- if (!_methodHandlers.TryGetValue(key, out handler))
- {
- if (methodCall.Header.Interface == "org.freedesktop.DBus.Properties")
- {
- MessageReader reader = new MessageReader(methodCall, null);
- var interf = reader.ReadString();
- key = GetPropertyLookupKey(interf, methodCall.Header.Member, methodCall.Header.Signature);
- _methodHandlers.TryGetValue(key, out handler);
- }
- }
- if (handler != null)
- {
- if (_synchronizationContext == null)
- {
- try
- {
- return await handler(_object, methodCall, _factory).ConfigureAwait(false);
- }
- catch (DBusException be)
- {
- return MessageHelper.ConstructErrorReply(methodCall, be.ErrorName, be.ErrorMessage);
- }
- catch (Exception e)
- {
- return MessageHelper.ConstructErrorReply(methodCall, e.GetType().FullName, e.Message);
- }
- }
- else
- {
- var tcs = new TaskCompletionSource();
- _synchronizationContext.Post(async _ => {
- Message reply;
- try
- {
- reply = await handler(_object, methodCall, _factory).ConfigureAwait(false);
- }
- catch (DBusException be)
- {
- reply = MessageHelper.ConstructErrorReply(methodCall, be.ErrorName, be.ErrorMessage);
- }
- catch (Exception e)
- {
- reply = MessageHelper.ConstructErrorReply(methodCall, e.GetType().FullName, e.Message);
- }
- tcs.SetResult(reply);
- }, null);
- return await tcs.Task.ConfigureAwait(false);
- }
- }
- else
- {
- var errorMessage = String.Format("Method \"{0}\" with signature \"{1}\" on interface \"{2}\" doesn't exist",
- methodCall.Header.Member,
- methodCall.Header.Signature?.Value,
- methodCall.Header.Interface);
-
- var replyMessage = MessageHelper.ConstructErrorReply(methodCall, "org.freedesktop.DBus.Error.UnknownMethod", errorMessage);
-
- return replyMessage;
- }
- }
-
- protected internal virtual Task[] StartWatchingSignals()
- {
- return Array.Empty>();
- }
-
- protected internal void EmitVoidSignal(string interfaceName, string signalName)
- {
- EmitNonVoidSignal(interfaceName, signalName, null, null);
- }
-
- protected internal void EmitNonVoidSignal(string iface, string member, Signature? inSigStr, MessageWriter writer)
- {
- if (!IsRegistered)
- {
- return;
- }
-
- Message signalMsg = new Message(
- new Header(MessageType.Signal)
- {
- Path = _objectPath2,
- Interface = iface,
- Member = member,
- Signature = inSigStr
- },
- writer?.ToArray(),
- writer?.UnixFds
- );
-
- _connection.EmitSignal(signalMsg);
- }
-
- protected internal async Task CreateNonVoidReply(Message methodCall, Task resultTask, Action writeResult, Signature? outSignature)
- {
- uint serial = methodCall.Header.Serial;
-
- T result = await resultTask.ConfigureAwait(false);
- MessageWriter retWriter = new MessageWriter();
- writeResult(retWriter, result);
-
- Message replyMsg = new Message(
- new Header(MessageType.MethodReturn)
- {
- Signature = outSignature
- },
- retWriter.ToArray(),
- retWriter.UnixFds
- );
- return replyMsg;
- }
-
- protected internal async Task CreateVoidReply(Message methodCall, Task task)
- {
- uint serial = methodCall.Header.Serial;
- await task.ConfigureAwait(false);
- var replyMsg = new Message(
- new Header(MessageType.MethodReturn),
- body: null,
- unixFds: null
- );
- return replyMsg;
- }
-
- private Task HandleIntrospect(object o, Message methodCall, IProxyFactory factory)
- {
- IntrospectionWriter writer = new IntrospectionWriter();
-
- writer.WriteDocType();
- writer.WriteNodeStart(_objectPath2.Value);
- writer.WriteLiteral(_typeIntrospection);
- foreach (var child in _connection.GetChildNames(_objectPath2))
- {
- writer.WriteChildNode(child);
- }
- writer.WriteNodeEnd();
-
- var xml = writer.ToString();
- var response = MessageHelper.ConstructReply(methodCall, xml);
- return Task.FromResult(response);
- }
-
- private bool IsRegistered
- {
- get
- {
- lock (_gate)
- {
- return _state == State.Registered;
- }
- }
- }
- }
-}
diff --git a/src/Linux/Tmds.DBus/CodeGen/DBusAdapterTypeBuilder.cs b/src/Linux/Tmds.DBus/CodeGen/DBusAdapterTypeBuilder.cs
deleted file mode 100644
index a8580cbae9..0000000000
--- a/src/Linux/Tmds.DBus/CodeGen/DBusAdapterTypeBuilder.cs
+++ /dev/null
@@ -1,417 +0,0 @@
-// Copyright 2016 Tom Deseyn
-// This software is made available under the MIT License
-// See COPYING for details
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Reflection.Emit;
-using System.Threading;
-using System.Threading.Tasks;
-using Tmds.DBus.Protocol;
-
-namespace Tmds.DBus.CodeGen
-{
- internal class DBusAdapterTypeBuilder
- {
- private static readonly ConstructorInfo s_messageWriterConstructor = typeof(MessageWriter).GetConstructor(Type.EmptyTypes);
- private static readonly Type[] s_dbusAdaptorConstructorParameterTypes = new Type[] { typeof(DBusConnection), typeof(ObjectPath2), typeof(object), typeof(IProxyFactory), typeof(SynchronizationContext) };
- private static readonly ConstructorInfo s_baseConstructor = typeof(DBusAdapter).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, s_dbusAdaptorConstructorParameterTypes);
- private static readonly ConstructorInfo s_methodHandlerConstructor = typeof(DBusAdapter.MethodCallHandler).GetConstructors()[0];
- private static readonly ConstructorInfo s_signatureConstructor = typeof(Signature).GetConstructor(new Type[] { typeof(string) });
- private static readonly ConstructorInfo s_nullableSignatureConstructor = typeof(Signature?).GetConstructor(new Type[] { typeof(Signature) });
- private static readonly ConstructorInfo s_messageReaderConstructor = typeof(MessageReader).GetConstructor(new Type[] { typeof(Message), typeof(IProxyFactory) });
- private static readonly FieldInfo s_methodDictionaryField = typeof(DBusAdapter).GetField(nameof(DBusAdapter._methodHandlers), BindingFlags.Instance | BindingFlags.NonPublic);
- private static readonly FieldInfo s_objectField = typeof(DBusAdapter).GetField(nameof(DBusAdapter._object), BindingFlags.Instance | BindingFlags.NonPublic);
- private static readonly MethodInfo s_methodDictionaryAdd = typeof(Dictionary).GetMethod("Add", new Type[] { typeof(string), typeof(DBusAdapter.MethodCallHandler) });
- private static readonly MethodInfo s_startWatchingSignals = typeof(DBusAdapter).GetMethod(nameof(DBusAdapter.StartWatchingSignals), BindingFlags.Instance | BindingFlags.NonPublic);
- private static readonly MethodInfo s_emitVoidSignal = typeof(DBusAdapter).GetMethod(nameof(DBusAdapter.EmitVoidSignal), BindingFlags.Instance | BindingFlags.NonPublic);
- private static readonly MethodInfo s_emitNonVoidSignal = typeof(DBusAdapter).GetMethod(nameof(DBusAdapter.EmitNonVoidSignal), BindingFlags.Instance | BindingFlags.NonPublic);
- private static readonly MethodInfo s_createNonVoidReply = typeof(DBusAdapter).GetMethod(nameof(DBusAdapter.CreateNonVoidReply), BindingFlags.Instance | BindingFlags.NonPublic);
- private static readonly MethodInfo s_createVoidReply = typeof(DBusAdapter).GetMethod(nameof(DBusAdapter.CreateVoidReply), BindingFlags.Instance | BindingFlags.NonPublic);
- private static readonly MethodInfo s_readerSkipString = typeof(MessageReader).GetMethod(nameof(MessageReader.SkipString), BindingFlags.Instance | BindingFlags.Public);
- private static readonly MethodInfo s_writerWriteString = typeof(MessageWriter).GetMethod(nameof(MessageWriter.WriteString), BindingFlags.Instance | BindingFlags.Public);
- private static readonly MethodInfo s_writerSetSkipNextStructPadding = typeof(MessageWriter).GetMethod(nameof(MessageWriter.SetSkipNextStructPadding), BindingFlags.Instance | BindingFlags.Public);
- private static readonly FieldInfo s_setTypeIntrospectionField = typeof(DBusAdapter).GetField(nameof(DBusAdapter._typeIntrospection), BindingFlags.Instance | BindingFlags.NonPublic);
- private static readonly Type s_taskOfMessageType = typeof(Task);
- private static readonly Type s_nullableSignatureType = typeof(Signature?);
- private static readonly Type s_action2GenericType = typeof(Action<,>);
- private static readonly Type s_messageWriterType = typeof(MessageWriter);
- private static readonly Type s_messageReaderType = typeof(MessageReader);
- // private static readonly Type s_stringType = typeof(string);
- private static readonly Type[] s_methodHandlerParameterTypes = new[] { typeof(object), typeof(Message), typeof(IProxyFactory) };
-
- private readonly ModuleBuilder _moduleBuilder;
- private TypeBuilder _typeBuilder;
-
- public DBusAdapterTypeBuilder(ModuleBuilder moduleBuilder)
- {
- _moduleBuilder = moduleBuilder;
- }
-
- public TypeInfo Build(Type objectType)
- {
- if (_typeBuilder != null)
- {
- throw new InvalidOperationException("Type has already been built.");
- }
-
- var parentType = typeof(DBusAdapter);
- var adapterName = objectType.FullName + "Adapter";
- _typeBuilder = _moduleBuilder.DefineType(adapterName, TypeAttributes.Class | TypeAttributes.Public, parentType);
-
- var description = TypeDescription.DescribeObject(objectType);
-
- ImplementConstructor(description);
- ImplementStartWatchingSignals(description.Interfaces);
-
- return _typeBuilder.CreateTypeInfo();
- }
-
- private void ImplementStartWatchingSignals(IList interfaces)
- {
- var signalCount = interfaces.Aggregate(0, (count, iface) => count +
- (iface.Signals?.Count ?? 0) +
- ((iface.PropertiesChangedSignal != null) ? 1 : 0));
- if (signalCount == 0)
- {
- return;
- }
-
- var method = _typeBuilder.OverrideAbstractMethod(s_startWatchingSignals);
- var ilg = method.GetILGenerator();
-
- // signals = new Task[signalCount];
- ilg.Emit(OpCodes.Ldc_I4, signalCount);
- ilg.Emit(OpCodes.Newarr, typeof(Task));
-
- var idx = 0;
- foreach (var dbusInterface in interfaces)
- {
- IEnumerable signals = dbusInterface.Signals ?? Array.Empty();
-
- if (dbusInterface.PropertiesChangedSignal != null)
- {
- signals = signals.Concat(new[] { dbusInterface.PropertiesChangedSignal });
- }
-
- foreach (var signal in signals)
- {
- // signals[i] = Watch((IDbusInterface)this, SendSignalAction)
- ilg.Emit(OpCodes.Dup); // signals
- ilg.Emit(OpCodes.Ldc_I4, idx); // i
-
- {
- // Watch(...)
- {
- // (IDbusInterface)this
- ilg.Emit(OpCodes.Ldarg_0);
- ilg.Emit(OpCodes.Ldfld, s_objectField);
- ilg.Emit(OpCodes.Castclass, dbusInterface.Type);
- }
-
- {
- //SendSignalAction
- ilg.Emit(OpCodes.Ldarg_0);
- ilg.Emit(OpCodes.Ldftn, GenSendSignal(signal, signal == dbusInterface.PropertiesChangedSignal));
- ilg.Emit(OpCodes.Newobj, signal.ActionType.GetConstructors()[0]);
- }
-
- if (signal.HasOnError)
- {
- // Action = null
- ilg.Emit(OpCodes.Ldnull);
- }
-
- ilg.Emit(OpCodes.Callvirt, signal.MethodInfo);
- }
-
- ilg.Emit(OpCodes.Stelem_Ref);
-
- idx++;
- }
- }
-
- ilg.Emit(OpCodes.Ret);
- }
-
- private void ImplementConstructor(TypeDescription typeDescription)
- {
- var dbusInterfaces = typeDescription.Interfaces;
- // DBusConnection connection, ObjectPath objectPath, object o, IProxyFactory factory
- var constructor = _typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, s_dbusAdaptorConstructorParameterTypes);
- var ilg = constructor.GetILGenerator();
-
- {
- // base constructor
- ilg.Emit(OpCodes.Ldarg_0); // this
- ilg.Emit(OpCodes.Ldarg_1); // DBusConnection
- ilg.Emit(OpCodes.Ldarg_2); // ObjectPath
- ilg.Emit(OpCodes.Ldarg_3); // object
- ilg.Emit(OpCodes.Ldarg, 4); // IProxyFactory
- ilg.Emit(OpCodes.Ldarg, 5); // SynchronizationContext
- ilg.Emit(OpCodes.Call, s_baseConstructor);
- }
-
- var introspectionXml = GenerateIntrospectionXml(typeDescription);
- ilg.Emit(OpCodes.Ldarg_0);
- ilg.Emit(OpCodes.Ldstr, introspectionXml);
- ilg.Emit(OpCodes.Stfld, s_setTypeIntrospectionField);
-
- foreach (var dbusInterface in dbusInterfaces)
- {
- IEnumerable methods = dbusInterface.Methods ?? Array.Empty();
-
- var propertyMethods = new[] { dbusInterface.GetPropertyMethod,
- dbusInterface.GetAllPropertiesMethod,
- dbusInterface.SetPropertyMethod };
-
- methods = methods.Concat(propertyMethods);
-
- foreach (var method in methods)
- {
- if (method == null)
- {
- continue;
- }
-
- if (method.IsGenericOut)
- {
- throw new NotImplementedException($"Cannot adaptor class for generic method {method.MethodInfo.ToString()}. Refactor the method to return Task