From 4f9e4b9f40eab5ed316ba4dd39e30aabcdf4e551 Mon Sep 17 00:00:00 2001 From: Mark Lechtermann Date: Mon, 15 Apr 2024 16:40:56 +0200 Subject: [PATCH] feat: Added var doc string for Enums --- .vscode/settings.json | 26 +- src/dscom.test/tests/EnumTest.cs | 238 +++++++++++------- src/dscom/exporter/FunctionInfo.cs | 195 +++++++------- src/dscom/exporter/TypeInfo.cs | 150 +++++------ src/dscom/exporter/VariableDescriptionInfo.cs | 77 +++--- src/dscom/writer/EnumWriter.cs | 10 +- 6 files changed, 379 insertions(+), 317 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 6d967ff..3a817e0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,14 +1,14 @@ -{ - "dotnet-test-explorer.testProjectPath": "src\\dscom.test\\dscom.test.csproj", - "editor.quickSuggestions": { - "comments": "on", - "strings": "on", - "other": "on" - }, - "editor.suggestOnTriggerCharacters": true, - "editor.codeActionsOnSave": { - "source.organizeImports": true - }, - "omnisharp.enableRoslynAnalyzers": true, - "omnisharp.enableEditorConfigSupport": true, +{ + "dotnet-test-explorer.testProjectPath": "src\\dscom.test\\dscom.test.csproj", + "editor.quickSuggestions": { + "comments": "on", + "strings": "on", + "other": "on" + }, + "editor.suggestOnTriggerCharacters": true, + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit" + }, + "omnisharp.enableRoslynAnalyzers": true, + "omnisharp.enableEditorConfigSupport": true, } \ No newline at end of file diff --git a/src/dscom.test/tests/EnumTest.cs b/src/dscom.test/tests/EnumTest.cs index d8c30f5..dfb27ca 100644 --- a/src/dscom.test/tests/EnumTest.cs +++ b/src/dscom.test/tests/EnumTest.cs @@ -1,96 +1,142 @@ -// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Runtime.InteropServices; - -namespace dSPACE.Runtime.InteropServices.Tests; - -public class EnumTest : BaseTest -{ - [Theory] - [InlineData(typeof(byte))] - [InlineData(typeof(sbyte))] - [InlineData(typeof(short))] - [InlineData(typeof(ushort))] - [InlineData(typeof(uint))] - [InlineData(typeof(int))] - [InlineData(typeof(ulong))] - [InlineData(typeof(long))] - public void EnumWithNumericValues_Available(Type type) - { - var result = CreateAssembly(CreateAssemblyName(assemblyNameSuffix: $"{type}")) - .WithEnum("TestEnum", type) - .WithLiteral("A", 1) - .WithLiteral("B", 20) - .WithLiteral("C", 50) - .Build() - .Build(); - - var typeLibInfo = result.TypeLib.GetTypeInfoByName("TestEnum"); - typeLibInfo.Should().NotBeNull(); - - var kv = typeLibInfo!.GetAllEnumValues(); - - kv.Should().Contain(new KeyValuePair("TestEnum_A", 1)); - kv.Should().Contain(new KeyValuePair("TestEnum_B", 20)); - kv.Should().Contain(new KeyValuePair("TestEnum_C", 50)); - } - - [Fact] - public void EnumComVisibleFalse_EnumIsNotGenerated() - { - var result = CreateAssembly() - .WithEnum("TestEnum") - .WithCustomAttribute(false) - .WithLiteral("A", 1) - .WithLiteral("B", 20) - .WithLiteral("C", 50) - .Build() - .Build(); - - var typeLibInfo = result.TypeLib.GetTypeInfoByName("TestEnum"); - typeLibInfo.Should().BeNull(); - } - - [Fact] - public void TwoEnumsWithTheSameNameInDifferentNamespaces_EnumFieldsShouldUseNamespaceAsPrefix() - { - var result = CreateAssembly() - .WithEnum("TestEnum").WithNamespace("dspace.test.namespace1") - .WithLiteral("A", 1) - .WithLiteral("B", 2) - .Build() - .WithEnum("TestEnum").WithNamespace("dspace.test.namespace2") - .WithLiteral("A", 1) - .WithLiteral("B", 2) - .Build() - .Build(); - - var typeLibInfo = result.TypeLib.GetTypeInfoByName("dspace_test_namespace1_TestEnum"); - typeLibInfo.Should().NotBeNull(); - var kv = typeLibInfo!.GetAllEnumValues(); - kv.ToList().Select(kv => kv.Key).Should().Contain("dspace_test_namespace1_TestEnum_A"); - kv.ToList().Select(kv => kv.Key).Should().Contain("dspace_test_namespace1_TestEnum_B"); - kv.ToList().Select(kv => kv.Key).Should().NotContain("TestEnum_A"); - kv.ToList().Select(kv => kv.Key).Should().NotContain("TestEnum_B"); - - typeLibInfo = result.TypeLib.GetTypeInfoByName("dspace_test_namespace2_TestEnum"); - typeLibInfo.Should().NotBeNull(); - kv = typeLibInfo!.GetAllEnumValues(); - kv.ToList().Select(kv => kv.Key).Should().Contain("dspace_test_namespace2_TestEnum_A"); - kv.ToList().Select(kv => kv.Key).Should().Contain("dspace_test_namespace2_TestEnum_B"); - kv.ToList().Select(kv => kv.Key).Should().NotContain("TestEnum_A"); - kv.ToList().Select(kv => kv.Key).Should().NotContain("TestEnum_B"); - } -} +// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace dSPACE.Runtime.InteropServices.Tests; + +public class EnumTest : BaseTest +{ + [Theory] + [InlineData(typeof(byte))] + [InlineData(typeof(sbyte))] + [InlineData(typeof(short))] + [InlineData(typeof(ushort))] + [InlineData(typeof(uint))] + [InlineData(typeof(int))] + [InlineData(typeof(ulong))] + [InlineData(typeof(long))] + public void EnumWithNumericValues_Available(Type type) + { + var result = CreateAssembly(CreateAssemblyName(assemblyNameSuffix: $"{type}")) + .WithEnum("TestEnum", type) + .WithLiteral("A", 1) + .WithLiteral("B", 20) + .WithLiteral("C", 50) + .Build() + .Build(); + + var typeLibInfo = result.TypeLib.GetTypeInfoByName("TestEnum"); + typeLibInfo.Should().NotBeNull(); + + var kv = typeLibInfo!.GetAllEnumValues(); + + kv.Should().Contain(new KeyValuePair("TestEnum_A", 1)); + kv.Should().Contain(new KeyValuePair("TestEnum_B", 20)); + kv.Should().Contain(new KeyValuePair("TestEnum_C", 50)); + } + + [Fact] + public void EnumComVisibleFalse_EnumIsNotGenerated() + { + var result = CreateAssembly() + .WithEnum("TestEnum") + .WithCustomAttribute(false) + .WithLiteral("A", 1) + .WithLiteral("B", 20) + .WithLiteral("C", 50) + .Build() + .Build(); + + var typeLibInfo = result.TypeLib.GetTypeInfoByName("TestEnum"); + typeLibInfo.Should().BeNull(); + } + + [Fact] + public void TwoEnumsWithTheSameNameInDifferentNamespaces_EnumFieldsShouldUseNamespaceAsPrefix() + { + var result = CreateAssembly() + .WithEnum("TestEnum").WithNamespace("dspace.test.namespace1") + .WithLiteral("A", 1) + .WithLiteral("B", 2) + .Build() + .WithEnum("TestEnum").WithNamespace("dspace.test.namespace2") + .WithLiteral("A", 1) + .WithLiteral("B", 2) + .Build() + .Build(); + + var typeLibInfo = result.TypeLib.GetTypeInfoByName("dspace_test_namespace1_TestEnum"); + typeLibInfo.Should().NotBeNull(); + var kv = typeLibInfo!.GetAllEnumValues(); + kv.ToList().Select(kv => kv.Key).Should().Contain("dspace_test_namespace1_TestEnum_A"); + kv.ToList().Select(kv => kv.Key).Should().Contain("dspace_test_namespace1_TestEnum_B"); + kv.ToList().Select(kv => kv.Key).Should().NotContain("TestEnum_A"); + kv.ToList().Select(kv => kv.Key).Should().NotContain("TestEnum_B"); + + typeLibInfo = result.TypeLib.GetTypeInfoByName("dspace_test_namespace2_TestEnum"); + typeLibInfo.Should().NotBeNull(); + kv = typeLibInfo!.GetAllEnumValues(); + kv.ToList().Select(kv => kv.Key).Should().Contain("dspace_test_namespace2_TestEnum_A"); + kv.ToList().Select(kv => kv.Key).Should().Contain("dspace_test_namespace2_TestEnum_B"); + kv.ToList().Select(kv => kv.Key).Should().NotContain("TestEnum_A"); + kv.ToList().Select(kv => kv.Key).Should().NotContain("TestEnum_B"); + } + + [Fact] + public void EnumsValuesWithDescription_EnumValueHasDocString() + { + var result = CreateAssembly() + .WithEnum("TestEnum").WithNamespace("dspace.test.namespace1") + .WithLiteralAndAttribute("A", 1, typeof(DescriptionAttribute), new Type[] { typeof(string) }, new object[] { "TestDescription_A" }) + .WithLiteralAndAttribute("B", 1, typeof(DescriptionAttribute), new Type[] { typeof(string) }, new object[] { "TestDescription_B" }) + .Build() + .Build(); + + var typeInfo = result.TypeLib.GetTypeInfoByName("TestEnum"); + typeInfo.Should().NotBeNull(); + + using var attribute = typeInfo!.GetTypeInfoAttributes(); + attribute.Should().NotBeNull(); + var count = attribute!.Value.cVars; + count.Should().Be(2); + typeInfo!.GetVarDesc(0, out var ppVarDesc0); + try + { + var varDesc = Marshal.PtrToStructure(ppVarDesc0); + varDesc.varkind.Should().Be(VARKIND.VAR_CONST); + typeInfo!.GetDocumentation(varDesc.memid, out _, out var strDocString, out _, out _); + strDocString.Should().Be("TestDescription_A"); + } + finally + { + typeInfo.ReleaseVarDesc(ppVarDesc0); + } + + typeInfo!.GetVarDesc(1, out var ppVarDesc1); + try + { + var varDesc = Marshal.PtrToStructure(ppVarDesc1); + varDesc.varkind.Should().Be(VARKIND.VAR_CONST); + typeInfo!.GetDocumentation(varDesc.memid, out _, out var strDocString, out _, out _); + strDocString.Should().Be("TestDescription_B"); + } + finally + { + typeInfo.ReleaseVarDesc(ppVarDesc1); + } + } +} + diff --git a/src/dscom/exporter/FunctionInfo.cs b/src/dscom/exporter/FunctionInfo.cs index 6478226..af2bbd5 100644 --- a/src/dscom/exporter/FunctionInfo.cs +++ b/src/dscom/exporter/FunctionInfo.cs @@ -1,95 +1,100 @@ -// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Runtime.InteropServices; - -namespace dSPACE.Runtime.InteropServices.Exporter; - -internal sealed class FunctionInfo : BaseInfo -{ - public FunctionInfo(ITypeInfo2 typeInfo, FUNCDESC funcDesc, BaseInfo? parent, string itemName) : base(parent, itemName) - { - typeInfo.GetDocumentation(funcDesc.memid, out _, out _, out _, out _); - var names = new string[funcDesc.cParams + 1]; - typeInfo.GetNames(funcDesc.memid, names, funcDesc.cParams + 1, out _); - Name = names[0]; - - MemberId = funcDesc.memid; - CallConv = funcDesc.callconv; - Kind = funcDesc.funckind.ToString(); - InvokeKind = funcDesc.invkind.ToString(); - FunctionFlags = funcDesc.wFuncFlags; - NumberOfParameters = funcDesc.cParams; - VTableOffset = funcDesc.oVft; - - var ptr = funcDesc.lprgelemdescParam; - - var size = Marshal.SizeOf(); - for (var i = 0; i < NumberOfParameters; i++) - { - var parameter = Marshal.PtrToStructure(ptr); - Parameters.Add(new ElementDescriptionInfo(typeInfo, parameter, names[i + 1], this, nameof(Parameters)) { OwningCollection = Parameters }); - ptr += size; - } - - if (VarEnum.VT_EMPTY != (VarEnum)funcDesc.elemdescFunc.tdesc.vt) - { - ReturnType = new ElementDescriptionInfo(typeInfo, funcDesc.elemdescFunc, string.Empty, this, nameof(ReturnType)); - } - - UpdateCustomData(typeInfo); - } - - public string Name { get; private set; } - - public int MemberId { get; } - - public CALLCONV CallConv { get; private set; } - - public string Kind { get; private set; } - - public string InvokeKind { get; private set; } - - public short FunctionFlags { get; private set; } - - public short NumberOfParameters { get; private set; } - - public short VTableOffset { get; private set; } - - public ElementDescriptionInfo? ReturnType { get; private set; } - - public List Parameters { get; } = new List(); - - public List CustomData { get; } = new List(); - - private void UpdateCustomData(ITypeInfo2 typeInfo) - { - var customDataPtr = Marshal.AllocHGlobal(Marshal.SizeOf()); - try - { - typeInfo.GetAllCustData(customDataPtr); - - var customData = Marshal.PtrToStructure(customDataPtr); - - for (var i = 0; i < customData.cCustData; i++) - { - CustomData.Add(new CustomDataItemInfo(customData.Items[i], this, nameof(CustomData)) { OwningCollection = CustomData }); - } - } - finally - { - Marshal.FreeHGlobal(customDataPtr); - } - } -} +// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Runtime.InteropServices; + +namespace dSPACE.Runtime.InteropServices.Exporter; + +internal sealed class FunctionInfo : BaseInfo +{ + public FunctionInfo(ITypeInfo2 typeInfo, FUNCDESC funcDesc, BaseInfo? parent, string itemName) : base(parent, itemName) + { + typeInfo.GetDocumentation(funcDesc.memid, out _, out var strDocString, out _, out _); + var names = new string[funcDesc.cParams + 1]; + typeInfo.GetNames(funcDesc.memid, names, funcDesc.cParams + 1, out _); + Name = names[0]; + + DocString = strDocString ?? string.Empty; + MemberId = funcDesc.memid; + CallConv = funcDesc.callconv; + Kind = funcDesc.funckind.ToString(); + InvokeKind = funcDesc.invkind.ToString(); + FunctionFlags = funcDesc.wFuncFlags; + NumberOfParameters = funcDesc.cParams; + VTableOffset = funcDesc.oVft; + + // typeInfo.GetDocumentation2(funcDesc.memid, out _, out _, out _, ); + + var ptr = funcDesc.lprgelemdescParam; + + var size = Marshal.SizeOf(); + for (var i = 0; i < NumberOfParameters; i++) + { + var parameter = Marshal.PtrToStructure(ptr); + Parameters.Add(new ElementDescriptionInfo(typeInfo, parameter, names[i + 1], this, nameof(Parameters)) { OwningCollection = Parameters }); + ptr += size; + } + + if (VarEnum.VT_EMPTY != (VarEnum)funcDesc.elemdescFunc.tdesc.vt) + { + ReturnType = new ElementDescriptionInfo(typeInfo, funcDesc.elemdescFunc, string.Empty, this, nameof(ReturnType)); + } + + UpdateCustomData(typeInfo); + } + + public string Name { get; private set; } + + public int MemberId { get; } + + public string DocString { get; private set; } + + public CALLCONV CallConv { get; private set; } + + public string Kind { get; private set; } + + public string InvokeKind { get; private set; } + + public short FunctionFlags { get; private set; } + + public short NumberOfParameters { get; private set; } + + public short VTableOffset { get; private set; } + + public ElementDescriptionInfo? ReturnType { get; private set; } + + public List Parameters { get; } = new List(); + + public List CustomData { get; } = new List(); + + private void UpdateCustomData(ITypeInfo2 typeInfo) + { + var customDataPtr = Marshal.AllocHGlobal(Marshal.SizeOf()); + try + { + typeInfo.GetAllCustData(customDataPtr); + + var customData = Marshal.PtrToStructure(customDataPtr); + + for (var i = 0; i < customData.cCustData; i++) + { + CustomData.Add(new CustomDataItemInfo(customData.Items[i], this, nameof(CustomData)) { OwningCollection = CustomData }); + } + } + finally + { + Marshal.FreeHGlobal(customDataPtr); + } + } +} diff --git a/src/dscom/exporter/TypeInfo.cs b/src/dscom/exporter/TypeInfo.cs index b9c5e3f..14040cf 100644 --- a/src/dscom/exporter/TypeInfo.cs +++ b/src/dscom/exporter/TypeInfo.cs @@ -1,75 +1,75 @@ -// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Runtime.InteropServices; - -namespace dSPACE.Runtime.InteropServices.Exporter; - -internal sealed class TypeInfo : BaseInfo -{ - public TypeInfo(ITypeInfo2 typeInfo, BaseInfo? parent, string itemName) : base(parent, itemName) - { - typeInfo.GetDocumentation(-1, out var typeName, out var docString, out var helpContext, out var helpFile); - - Name = typeName; - DocString = docString; - HelpContext = helpContext; - HelpFile = helpFile; - Attributes = new TypeAttributeInfo(typeInfo, this, nameof(Attributes)); - - if (Attributes.Kind is TYPEKIND.TKIND_ENUM or TYPEKIND.TKIND_RECORD) - { - for (var i = 0; i < Attributes.NumberOfVariablesAndDatafields; i++) - { - typeInfo.GetVarDesc(i, out var ppvarDesc); - var varDesc = Marshal.PtrToStructure(ppvarDesc); - VariableDescription.Add(new VariableDescriptionInfo(typeInfo, varDesc, this, nameof(VariableDescription)) { OwningCollection = VariableDescription }); - typeInfo.ReleaseVarDesc(ppvarDesc); - } - } - - for (var i = 0; i < Attributes.NumberOfImplementedInterfaces; i++) - { - typeInfo.GetRefTypeOfImplType(i, out var href); - typeInfo.GetRefTypeInfo(href, out var refTypeInfo); - var refTypeInfo2 = (ITypeInfo2)refTypeInfo; - ImplementedInterfaces.Add(new ImplementationReferenceTypeInfo(refTypeInfo2, typeInfo, i, this, nameof(ImplementedInterfaces)) { OwningCollection = ImplementedInterfaces }); - } - - for (var i = 0; i < Attributes.NumberOfFunctions; i++) - { - typeInfo.GetFuncDesc(i, out var ppFuncDesc); - var funcDesc = Marshal.PtrToStructure(ppFuncDesc); - var method = new FunctionInfo(typeInfo, funcDesc, this, nameof(Functions)) { OwningCollection = Functions }; - Functions.Add(method); - typeInfo.ReleaseFuncDesc(ppFuncDesc); - } - } - - public string Name { get; private set; } - - public string DocString { get; private set; } - - public int HelpContext { get; private set; } - - public string HelpFile { get; private set; } - - public TypeAttributeInfo Attributes { get; private set; } - - public List ImplementedInterfaces { get; } = new List(); - - public List VariableDescription { get; } = new List(); - - public List Functions { get; } = new List(); -} +// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Runtime.InteropServices; + +namespace dSPACE.Runtime.InteropServices.Exporter; + +internal sealed class TypeInfo : BaseInfo +{ + public TypeInfo(ITypeInfo2 typeInfo, BaseInfo? parent, string itemName) : base(parent, itemName) + { + typeInfo.GetDocumentation(-1, out var typeName, out var docString, out var helpContext, out var helpFile); + + Name = typeName; + DocString = docString; + HelpContext = helpContext; + HelpFile = helpFile; + Attributes = new TypeAttributeInfo(typeInfo, this, nameof(Attributes)); + + if (Attributes.Kind is TYPEKIND.TKIND_ENUM or TYPEKIND.TKIND_RECORD) + { + for (var i = 0; i < Attributes.NumberOfVariablesAndDatafields; i++) + { + typeInfo.GetVarDesc(i, out var ppvarDesc); + var varDesc = Marshal.PtrToStructure(ppvarDesc); + VariableDescription.Add(new VariableDescriptionInfo(typeInfo, varDesc, this, nameof(VariableDescription)) { OwningCollection = VariableDescription }); + typeInfo.ReleaseVarDesc(ppvarDesc); + } + } + + for (var i = 0; i < Attributes.NumberOfImplementedInterfaces; i++) + { + typeInfo.GetRefTypeOfImplType(i, out var href); + typeInfo.GetRefTypeInfo(href, out var refTypeInfo); + var refTypeInfo2 = (ITypeInfo2)refTypeInfo; + ImplementedInterfaces.Add(new ImplementationReferenceTypeInfo(refTypeInfo2, typeInfo, i, this, nameof(ImplementedInterfaces)) { OwningCollection = ImplementedInterfaces }); + } + + for (var i = 0; i < Attributes.NumberOfFunctions; i++) + { + typeInfo.GetFuncDesc(i, out var ppFuncDesc); + var funcDesc = Marshal.PtrToStructure(ppFuncDesc); + var method = new FunctionInfo(typeInfo, funcDesc, this, nameof(Functions)) { OwningCollection = Functions }; + Functions.Add(method); + typeInfo.ReleaseFuncDesc(ppFuncDesc); + } + } + + public string Name { get; private set; } + + public string DocString { get; private set; } + + public int HelpContext { get; private set; } + + public string HelpFile { get; private set; } + + public TypeAttributeInfo Attributes { get; private set; } + + public List ImplementedInterfaces { get; } = new List(); + + public List VariableDescription { get; } = new List(); + + public List Functions { get; } = new List(); +} diff --git a/src/dscom/exporter/VariableDescriptionInfo.cs b/src/dscom/exporter/VariableDescriptionInfo.cs index b2a1775..c225fbd 100644 --- a/src/dscom/exporter/VariableDescriptionInfo.cs +++ b/src/dscom/exporter/VariableDescriptionInfo.cs @@ -1,37 +1,40 @@ -// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Runtime.InteropServices; - -namespace dSPACE.Runtime.InteropServices.Exporter; - -internal sealed class VariableDescriptionInfo : BaseInfo -{ - public VariableDescriptionInfo(ITypeInfo2 typeInfo, VARDESC varDesc, BaseInfo? parent, string itemName) : base(parent, itemName) - { - if (varDesc.varkind is VARKIND.VAR_CONST or VARKIND.VAR_PERINSTANCE) - { - typeInfo!.GetDocumentation(varDesc.memid, out var name, out _, out _, out _); - Name = string.IsNullOrEmpty(name) ? null : name; - Value = new TypeDescriptionInfo(typeInfo, varDesc.elemdescVar.tdesc, this, nameof(Value)); - Type = (VarEnum)varDesc.elemdescVar.tdesc.vt; - } - } - - public string? Name { get; private set; } - - public VarEnum? Type { get; private set; } - - public object? Value { get; private set; } -} +// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Runtime.InteropServices; + +namespace dSPACE.Runtime.InteropServices.Exporter; + +internal sealed class VariableDescriptionInfo : BaseInfo +{ + public VariableDescriptionInfo(ITypeInfo2 typeInfo, VARDESC varDesc, BaseInfo? parent, string itemName) : base(parent, itemName) + { + if (varDesc.varkind is VARKIND.VAR_CONST or VARKIND.VAR_PERINSTANCE) + { + typeInfo!.GetDocumentation(varDesc.memid, out var name, out var docString, out _, out _); + DocString = docString ?? string.Empty; + Name = string.IsNullOrEmpty(name) ? null : name; + Value = new TypeDescriptionInfo(typeInfo, varDesc.elemdescVar.tdesc, this, nameof(Value)); + Type = (VarEnum)varDesc.elemdescVar.tdesc.vt; + } + } + + public string? Name { get; private set; } + + public VarEnum? Type { get; private set; } + + public object? Value { get; private set; } + + public object? DocString { get; private set; } +} diff --git a/src/dscom/writer/EnumWriter.cs b/src/dscom/writer/EnumWriter.cs index 75e5eee..64debc2 100644 --- a/src/dscom/writer/EnumWriter.cs +++ b/src/dscom/writer/EnumWriter.cs @@ -12,7 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.ComponentModel; using System.Globalization; +using System.Reflection; using System.Runtime.InteropServices; namespace dSPACE.Runtime.InteropServices.Writer; @@ -30,7 +32,7 @@ public override void Create() uint index = 0; var fields = - SourceType.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static) + SourceType.GetFields(BindingFlags.Public | BindingFlags.Static) .OrderBy(field => field.MetadataToken); foreach (var field in fields) { @@ -57,6 +59,12 @@ public override void Create() .ThrowIfFailed($"Failed to add variable description for enum {SourceType}."); TypeInfo.SetVarName(index, Context.NameResolver.GetMappedName(field, $"{Name}_{field.Name}")) .ThrowIfFailed($"Failed to set variable name {field.Name} for enum {SourceType}."); + + // If the field has a DescriptionAttribute, use it as the variable description. + var descriptionAttribute = field.GetCustomAttribute(false); + TypeInfo.SetVarDocString(index, descriptionAttribute?.Description ?? string.Empty) + .ThrowIfFailed($"Failed to set variable description for enum {SourceType}."); + index++; }