Skip to content

Commit 2830576

Browse files
Fix broken behavior of IsVisibleInDynamoLibrary attribute with interfaces and Enums (#9242) (#9247)
* fix broken behavior of IsVisibleInDynamoLibrary attribute with interfaces * revert extraneous changes * fixes * added test * revert file * fix regression in IsVisibleInDynamoLibrary attribute applied to enum * add test for enum attribute fix
1 parent d36c736 commit 2830576

File tree

4 files changed

+171
-31
lines changed

4 files changed

+171
-31
lines changed

src/Engine/ProtoCore/FFI/CLRDLLModule.cs

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ static CLRModuleType()
4747
/// given type is not found, it creates a new one. If CLRDLLModule is
4848
/// passed as null, it creates empty CLRModuleType.
4949
/// </summary>
50-
/// <param name="module">CLRDLLModule which imports this type</param>
5150
/// <param name="type">System.Type to be imported in DesignScript</param>
51+
/// <param name="module">CLRDLLModule which imports this type</param>
5252
/// <param name="alias">Alias name, if any. For now its not supported.</param>
5353
public static CLRModuleType GetInstance(Type type, CLRDLLModule module, string alias)
5454
{
@@ -359,10 +359,10 @@ private ClassDeclNode ParseSystemType(Type type, string alias)
359359
// marked as sealed and abstract.
360360
classnode.IsStatic = type.IsAbstract && type.IsSealed;
361361

362+
// If all methods are static, it doesn't make sense to expose
363+
// constructor.
362364
if (!classnode.IsStatic)
363365
{
364-
// If all methods are static, it doesn't make sense to expose
365-
// constructor.
366366
ConstructorInfo[] ctors = type.GetConstructors();
367367
foreach (var c in ctors)
368368
{
@@ -663,23 +663,24 @@ private ProtoCore.AST.AssociativeAST.VarDeclNode ParseFieldDeclaration(FieldInfo
663663
return varDeclNode;
664664
}
665665

666-
private ProtoCore.AST.AssociativeAST.FunctionDefinitionNode ParseFieldAccessor(FieldInfo f)
666+
private FunctionDefinitionNode ParseFieldAccessor(FieldInfo f)
667667
{
668668
if (null == f || SupressesImport(f))
669669
return null;
670670

671-
ProtoCore.AST.AssociativeAST.FunctionDefinitionNode func = new ProtoCore.AST.AssociativeAST.FunctionDefinitionNode();
672-
func.Name = string.Format("{0}{1}", Constants.kGetterPrefix, f.Name);
673-
func.Signature = new ProtoCore.AST.AssociativeAST.ArgumentSignatureNode();
674-
func.ReturnType = CLRModuleType.GetProtoCoreType(f.FieldType, Module);
675-
func.FunctionBody = null;
676-
func.Access = ProtoCore.CompilerDefinitions.AccessModifier.Public;
677-
func.IsExternLib = true;
678-
func.ExternLibName = Module.Name;
679-
func.IsStatic = f.IsStatic;
680-
//Set the method attribute for Enum properties.
681-
func.MethodAttributes = new FFIMethodAttributes(f);
682-
671+
var func = new FunctionDefinitionNode
672+
{
673+
Name = string.Format("{0}{1}", Constants.kGetterPrefix, f.Name),
674+
Signature = new ArgumentSignatureNode(),
675+
ReturnType = CLRModuleType.GetProtoCoreType(f.FieldType, Module),
676+
FunctionBody = null,
677+
Access = ProtoCore.CompilerDefinitions.AccessModifier.Public,
678+
IsExternLib = true,
679+
ExternLibName = Module.Name,
680+
IsStatic = f.IsStatic,
681+
MethodAttributes = new FFIMethodAttributes(f),
682+
};
683+
683684
return func;
684685
}
685686

@@ -1225,6 +1226,9 @@ public FFIClassAttributes(Type type)
12251226
if (type == null)
12261227
throw new ArgumentNullException("type");
12271228

1229+
// Hide all interfaces from library and search
1230+
if (type.IsInterface) HiddenInLibrary = true;
1231+
12281232
attributes = type.GetCustomAttributes(false).Cast<Attribute>().ToArray();
12291233
foreach (var attr in attributes)
12301234
{
@@ -1268,24 +1272,45 @@ public FFIMethodAttributes(FieldInfo f)
12681272
{
12691273
var atts = f.GetCustomAttributes(false).Cast<Attribute>();
12701274

1275+
var parentAtts = f.DeclaringType.GetCustomAttributes(false).Cast<Attribute>();
1276+
var isObsolete = false;
1277+
var hidden = false;
1278+
var message = "";
1279+
foreach(var attr in parentAtts)
1280+
{
1281+
if(attr is ObsoleteAttribute)
1282+
{
1283+
isObsolete = true;
1284+
message = (attr as ObsoleteAttribute).Message;
1285+
if (string.IsNullOrEmpty(message))
1286+
message = "Obsolete";
1287+
}
1288+
1289+
if (attr is IsVisibleInDynamoLibraryAttribute)
1290+
{
1291+
hidden = !((IsVisibleInDynamoLibraryAttribute)attr).Visible;
1292+
}
1293+
}
1294+
12711295
foreach (var attr in atts)
12721296
{
12731297
//Set the obsolete message for enum fields.
1274-
if (attr is IsObsoleteAttribute)
1298+
if (attr is ObsoleteAttribute)
12751299
{
12761300
HiddenInLibrary = true;
1277-
ObsoleteMessage = (attr as IsObsoleteAttribute).Message;
1301+
ObsoleteMessage = (attr as ObsoleteAttribute).Message;
12781302
if (string.IsNullOrEmpty(ObsoleteMessage))
12791303
ObsoleteMessage = "Obsolete";
12801304
}
1281-
else if (attr is ObsoleteAttribute)
1305+
else if(attr is IsVisibleInDynamoLibraryAttribute)
12821306
{
1283-
HiddenInLibrary = true;
1284-
ObsoleteMessage = (attr as ObsoleteAttribute).Message;
1285-
if (string.IsNullOrEmpty(ObsoleteMessage))
1286-
ObsoleteMessage = "Obsolete";
1307+
HiddenInLibrary = !((IsVisibleInDynamoLibraryAttribute)attr).Visible;
12871308
}
1288-
1309+
}
1310+
if (isObsolete || hidden)
1311+
{
1312+
HiddenInLibrary = true;
1313+
if (isObsolete) ObsoleteMessage = message;
12891314
}
12901315
}
12911316

src/Libraries/CoreNodes/DateTime.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -233,21 +233,15 @@ public static System.TimeSpan TimeOfDay(System.DateTime dateTime)
233233
/// Days of the Week
234234
/// </summary>
235235
[IsVisibleInDynamoLibrary(false)]
236+
[Obsolete("This node is deprecated")]
236237
public enum DayOfWeek
237238
{
238-
[Obsolete("This node is deprecated")]
239239
[EnumDescription("EnumDateOfWeekSunday", typeof(Properties.Resources))]Sunday,
240-
[Obsolete("This node is deprecated")]
241240
[EnumDescription("EnumDateOfWeekMonday", typeof(Properties.Resources))]Monday,
242-
[Obsolete("This node is deprecated")]
243241
[EnumDescription("EnumDateOfWeekTuesday", typeof(Properties.Resources))]Tuesday,
244-
[Obsolete("This node is deprecated")]
245242
[EnumDescription("EnumDateOfWeekWednesday", typeof(Properties.Resources))]Wednesday,
246-
[Obsolete("This node is deprecated")]
247243
[EnumDescription("EnumDateOfWeekThursday", typeof(Properties.Resources))]Thursday,
248-
[Obsolete("This node is deprecated")]
249244
[EnumDescription("EnumDateOfWeekFriday", typeof(Properties.Resources))]Friday,
250-
[Obsolete("This node is deprecated")]
251245
[EnumDescription("EnumDateOfWeekSaturday", typeof(Properties.Resources))]Saturday
252246
}
253247

test/DynamoCoreWpfTests/LibraryTests.cs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using NUnit.Framework;
99
using ProtoCore;
1010
using System;
11+
using System.Linq;
1112
using System.Xml;
1213
using TestServices;
1314

@@ -151,5 +152,100 @@ public void DumpLibraryToXmlZeroTouchTest()
151152
}
152153
}
153154
}
155+
156+
[Test]
157+
public void SearchHiddenInterfaceNodeTest()
158+
{
159+
var searchViewModel = new SearchViewModel(new NodeSearchModel());
160+
161+
LibraryLoaded = false;
162+
163+
string libraryPath = "FFITarget.dll";
164+
165+
// All we need to do here is to ensure that the target has been loaded
166+
// at some point, so if it's already here, don't try and reload it
167+
if (!libraryServices.IsLibraryLoaded(libraryPath))
168+
{
169+
libraryServices.ImportLibrary(libraryPath);
170+
Assert.IsTrue(LibraryLoaded);
171+
}
172+
173+
var fgToCompare = libraryServices.GetFunctionGroups(libraryPath);
174+
foreach (var funcGroup in fgToCompare)
175+
{
176+
foreach (var functionDescriptor in funcGroup.Functions)
177+
{
178+
if (functionDescriptor.IsVisibleInLibrary && !functionDescriptor.DisplayName.Contains("GetType"))
179+
{
180+
searchViewModel.Model.Add(new ZeroTouchSearchElement(functionDescriptor));
181+
}
182+
}
183+
}
184+
185+
var searchString = "InterfaceA";
186+
var nodes = searchViewModel.Search(searchString);
187+
var foundNodes = nodes.Where(n => n.Class.Equals(searchString));
188+
Assert.IsFalse(foundNodes.Any());
189+
190+
searchString = "DerivedFromInterfaceA";
191+
nodes = searchViewModel.Search(searchString);
192+
foundNodes = nodes.Where(n => n.Class.Equals(searchString));
193+
Assert.AreEqual(2, foundNodes.Count());
194+
195+
searchString = "TraceableId";
196+
nodes = searchViewModel.Search(searchString);
197+
foundNodes = nodes.Where(n => n.Class.Equals(searchString));
198+
Assert.IsFalse(foundNodes.Any());
199+
200+
searchString = "ISerializable";
201+
nodes = searchViewModel.Search(searchString);
202+
foundNodes = nodes.Where(n => n.Class.Equals(searchString));
203+
Assert.IsFalse(foundNodes.Any());
204+
}
205+
206+
[Test]
207+
public void SearchHiddenEnumTest()
208+
{
209+
var searchViewModel = new SearchViewModel(new NodeSearchModel());
210+
211+
LibraryLoaded = false;
212+
213+
string libraryPath = "FFITarget.dll";
214+
215+
// All we need to do here is to ensure that the target has been loaded
216+
// at some point, so if it's already here, don't try and reload it
217+
if (!libraryServices.IsLibraryLoaded(libraryPath))
218+
{
219+
libraryServices.ImportLibrary(libraryPath);
220+
Assert.IsTrue(LibraryLoaded);
221+
}
222+
223+
var fgToCompare = libraryServices.GetFunctionGroups(libraryPath);
224+
foreach (var funcGroup in fgToCompare)
225+
{
226+
foreach (var functionDescriptor in funcGroup.Functions)
227+
{
228+
if (functionDescriptor.IsVisibleInLibrary && !functionDescriptor.DisplayName.Contains("GetType"))
229+
{
230+
searchViewModel.Model.Add(new ZeroTouchSearchElement(functionDescriptor));
231+
}
232+
}
233+
}
234+
235+
var searchString = "Days";
236+
var nodes = searchViewModel.Search(searchString);
237+
var foundNodes = nodes.Where(n => n.Class.Equals(searchString));
238+
Assert.IsFalse(foundNodes.Any());
239+
240+
searchString = "Sunday";
241+
nodes = searchViewModel.Search(searchString);
242+
foundNodes = nodes.Where(n => n.Class.Equals(searchString));
243+
Assert.IsFalse(foundNodes.Any());
244+
245+
searchString = "Tuesday";
246+
nodes = searchViewModel.Search(searchString);
247+
foundNodes = nodes.Where(n => n.Class.Equals(searchString));
248+
Assert.IsFalse(foundNodes.Any());
249+
}
154250
}
155251
}

test/Engine/FFITarget/CodeCompletionClass.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System;
33
using System.Collections.Generic;
44
using System.Linq;
5+
using System.Runtime.Serialization;
56
using System.Text;
67

78
namespace FFITarget
@@ -125,4 +126,28 @@ public class AnotherClassWithNameConflict
125126
public static string PropertyF { get; set; }
126127
}
127128
}
129+
130+
[IsVisibleInDynamoLibrary(false)]
131+
[Serializable]
132+
public class TraceableId : ISerializable
133+
{
134+
public int IntID { get; set; }
135+
136+
public void GetObjectData(SerializationInfo info, StreamingContext context)
137+
{
138+
info.AddValue("intID", IntID, typeof(int));
139+
}
140+
}
141+
142+
[IsVisibleInDynamoLibrary(false)]
143+
public enum Days
144+
{
145+
Sunday,
146+
Monday,
147+
Tuesday,
148+
Wednesday,
149+
Thursday,
150+
Friday,
151+
Saturday
152+
}
128153
}

0 commit comments

Comments
 (0)