summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2018-04-14 20:14:31 -0400
committerJesse Plamondon-Willard <github@jplamondonw.com>2018-04-14 20:14:31 -0400
commit1848abe7d57e32207db9535c9c83d96dbda64ced (patch)
tree64d4137e14e7fe7c09584289d5b5581fc34749ff
parent6d8cf614a24ab69baffa89c351b9a22776741442 (diff)
downloadSMAPI-1848abe7d57e32207db9535c9c83d96dbda64ced.tar.gz
SMAPI-1848abe7d57e32207db9535c9c83d96dbda64ced.tar.bz2
SMAPI-1848abe7d57e32207db9535c9c83d96dbda64ced.zip
don't warn for NetCollection conversion to implemented interface (#471)
-rw-r--r--src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/Netcode/NetCollection.cs10
-rw-r--r--src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/StardewValley/Farmer.cs7
-rw-r--r--src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/StardewValley/Item.cs9
-rw-r--r--src/SMAPI.ModBuildConfig.Analyzer.Tests/NetFieldAnalyzerTests.cs12
-rw-r--r--src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs11
5 files changed, 37 insertions, 12 deletions
diff --git a/src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/Netcode/NetCollection.cs b/src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/Netcode/NetCollection.cs
new file mode 100644
index 00000000..d160610e
--- /dev/null
+++ b/src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/Netcode/NetCollection.cs
@@ -0,0 +1,10 @@
+// ReSharper disable CheckNamespace -- matches Stardew Valley's code
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Netcode
+{
+ /// <summary>A simplified version of Stardew Valley's <c>Netcode.NetCollection</c> for unit testing.</summary>
+ public class NetCollection<T> : Collection<T>, IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable { }
+}
diff --git a/src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/StardewValley/Farmer.cs b/src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/StardewValley/Farmer.cs
index 54e91682..13fab069 100644
--- a/src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/StardewValley/Farmer.cs
+++ b/src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/StardewValley/Farmer.cs
@@ -1,7 +1,6 @@
// ReSharper disable CheckNamespace, InconsistentNaming -- matches Stardew Valley's code
#pragma warning disable 649 // (never assigned) -- only used to test type conversions
using System.Collections.Generic;
-using Netcode;
namespace StardewValley
{
@@ -10,11 +9,5 @@ namespace StardewValley
{
/// <summary>A sample field which should be replaced with a different property.</summary>
public readonly IDictionary<string, int[]> friendships;
-
- /// <summary>A sample net list.</summary>
- public readonly NetList<int> eventsSeen;
-
- /// <summary>A sample net object list.</summary>
- public readonly NetObjectList<int> netObjectList;
}
}
diff --git a/src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/StardewValley/Item.cs b/src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/StardewValley/Item.cs
index 386767d7..1b6317c1 100644
--- a/src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/StardewValley/Item.cs
+++ b/src/SMAPI.ModBuildConfig.Analyzer.Tests/Mock/StardewValley/Item.cs
@@ -20,5 +20,14 @@ namespace StardewValley
/// <summary>A generic net ref property with no equivalent non-net property.</summary>
public NetRef<object> netRefProperty { get; } = new NetRef<object>();
+
+ /// <summary>A sample net list.</summary>
+ public readonly NetList<int> netList = new NetList<int>();
+
+ /// <summary>A sample net object list.</summary>
+ public readonly NetObjectList<int> netObjectList = new NetObjectList<int>();
+
+ /// <summary>A sample net collection.</summary>
+ public readonly NetCollection<int> netCollection = new NetCollection<int>();
}
}
diff --git a/src/SMAPI.ModBuildConfig.Analyzer.Tests/NetFieldAnalyzerTests.cs b/src/SMAPI.ModBuildConfig.Analyzer.Tests/NetFieldAnalyzerTests.cs
index 15bcadcd..7b410085 100644
--- a/src/SMAPI.ModBuildConfig.Analyzer.Tests/NetFieldAnalyzerTests.cs
+++ b/src/SMAPI.ModBuildConfig.Analyzer.Tests/NetFieldAnalyzerTests.cs
@@ -86,7 +86,8 @@ namespace SMAPI.ModBuildConfig.Analyzer.Tests
[TestCase("SObject obj = null; if (obj.netRefField != null);", 24, "obj.netRefField", "NetRef", "object")]
[TestCase("SObject obj = null; if (obj.netRefProperty == null);", 24, "obj.netRefProperty", "NetRef", "object")]
[TestCase("SObject obj = null; if (obj.netRefProperty != null);", 24, "obj.netRefProperty", "NetRef", "object")]
- [TestCase("SFarmer farmer = new SFarmer(); object list = farmer.eventsSeen;", 46, "farmer.eventsSeen", "NetList", "object")] // ↓ NetList field converted to a non-interface type
+ [TestCase("Item item = new Item(); object list = item.netList;", 38, "item.netList", "NetList", "object")] // ↓ NetList field converted to a non-interface type
+ [TestCase("Item item = new Item(); object list = item.netCollection;", 38, "item.netCollection", "NetCollection", "object")]
public void AvoidImplicitNetFieldComparisons_RaisesDiagnostic(string codeText, int column, string expression, string fromType, string toType)
{
// arrange
@@ -105,10 +106,11 @@ namespace SMAPI.ModBuildConfig.Analyzer.Tests
/// <summary>Test that the net field analyzer doesn't raise any warnings for safe member access.</summary>
/// <param name="codeText">The code line to test.</param>
- [TestCase("SFarmer farmer = new SFarmer(); System.Collections.IEnumerable list = farmer.eventsSeen;")]
- [TestCase("SFarmer farmer = new SFarmer(); System.Collections.Generic.IEnumerable<int> list = farmer.eventsSeen;")]
- [TestCase("SFarmer farmer = new SFarmer(); System.Collections.Generic.IList<int> list = farmer.eventsSeen;")]
- [TestCase("SFarmer farmer = new SFarmer(); System.Collections.Generic.IList<int> list = farmer.netObjectList;")] // subclass of NetList
+ [TestCase("Item item = new Item(); System.Collections.IEnumerable list = farmer.eventsSeen;")]
+ [TestCase("Item item = new Item(); System.Collections.Generic.IEnumerable<int> list = farmer.netList;")]
+ [TestCase("Item item = new Item(); System.Collections.Generic.IList<int> list = farmer.netList;")]
+ [TestCase("Item item = new Item(); System.Collections.Generic.ICollection<int> list = farmer.netCollection;")]
+ [TestCase("Item item = new Item(); System.Collections.Generic.IList<int> list = farmer.netObjectList;")] // subclass of NetList
public void AvoidImplicitNetFieldComparisons_AllowsSafeAccess(string codeText)
{
// arrange
diff --git a/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs b/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs
index 7c8b804e..72d3bbf8 100644
--- a/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs
+++ b/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs
@@ -22,6 +22,9 @@ namespace StardewModdingAPI.ModBuildConfig.Analyzer
/// <summary>The full name for Stardew Valley's <c>Netcode.NetList</c> type.</summary>
private readonly string NetListTypeFullName = "Netcode.NetList";
+ /// <summary>The full name for Stardew Valley's <c>Netcode.NetCollection</c> type.</summary>
+ private readonly string NetCollectionTypeFullName = "Netcode.NetCollection";
+
/// <summary>Maps net fields to their equivalent non-net properties where available.</summary>
private readonly IDictionary<string, string> NetFieldWrapperProperties = new Dictionary<string, string>
{
@@ -232,6 +235,14 @@ namespace StardewModdingAPI.ModBuildConfig.Analyzer
return false;
}
+ // collection conversion to an implemented interface is OK
+ if (AnalyzerUtilities.GetConcreteTypes(typeInfo.Type).Any(p => p.ToString().StartsWith(this.NetCollectionTypeFullName))) // StartsWith to ignore generics
+ {
+ string toType = typeInfo.ConvertedType.ToString();
+ if (toType.StartsWith(typeof(IEnumerable<>).Namespace) || toType == typeof(IEnumerable).FullName)
+ return false;
+ }
+
// avoid any other conversions
return true;
}