From 5e0ea324c32581acd5c81993dc02dc9a38ff9bc4 Mon Sep 17 00:00:00 2001 From: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com> Date: Wed, 4 Sep 2024 12:49:35 +0100 Subject: [PATCH] Re-introduced code analysers and fixed many violations (#92) * Sdk * Objects * Supressed IDE warnings via editor config instead of nowarn * Nullability and other warnings * using * Fixed warnings * Important fix * More fixes --- .editorconfig | 12 ++ CodeMetricsConfig.txt | 4 + Directory.Build.props | 49 ++++- Directory.Build.targets | 14 ++ Speckle.Sdk.sln | 2 + build/Program.cs | 23 ++- src/Speckle.Objects/BuiltElements/Rebar.cs | 5 +- .../BuiltElements/Revit/FreeformElement.cs | 2 +- .../BuiltElements/Revit/RevitOpening.cs | 1 - .../BuiltElements/Revit/RevitRebar.cs | 2 +- .../BuiltElements/Revit/RevitWall.cs | 7 +- src/Speckle.Objects/EncodingOptimisations.cs | 4 +- src/Speckle.Objects/GIS/GisPointFeature.cs | 4 +- src/Speckle.Objects/GIS/GisPolylineFeature.cs | 4 +- src/Speckle.Objects/Geometry/Arc.cs | 3 +- src/Speckle.Objects/Geometry/Circle.cs | 2 +- src/Speckle.Objects/Geometry/Ellipse.cs | 2 +- src/Speckle.Objects/Geometry/Line.cs | 5 +- src/Speckle.Objects/Geometry/Mesh.cs | 1 - src/Speckle.Objects/Geometry/Plane.cs | 4 +- src/Speckle.Objects/Geometry/Point.cs | 4 +- src/Speckle.Objects/Geometry/Pointcloud.cs | 1 - src/Speckle.Objects/Geometry/Surface.cs | 2 +- src/Speckle.Objects/Other/Transform.cs | 1 - src/Speckle.Objects/Speckle.Objects.csproj | 7 + src/Speckle.Sdk.Logging/Consts.cs | 2 +- src/Speckle.Sdk.Logging/ISpeckleLogger.cs | 10 +- src/Speckle.Sdk.Logging/SpeckleActivity.cs | 2 +- src/Speckle.Sdk.Logging/SpeckleLogger.cs | 12 +- src/Speckle.Sdk/Api/Exceptions.cs | 1 - src/Speckle.Sdk/Api/GraphQL/Client.cs | 23 +-- .../Client.ActivityOperations.cs | 3 +- .../Client.ServerOperations.cs | 5 +- .../Client.StreamOperations.cs | 189 +----------------- .../Client.Subscriptions.Branch.cs | 83 +------- .../Client.Subscriptions.Commit.cs | 96 ++------- .../Client.Subscriptions.Stream.cs | 110 ++-------- .../Api/GraphQL/Legacy/LegacyGraphQLModels.cs | 36 +--- src/Speckle.Sdk/Api/GraphQL/Legacy/Manager.cs | 96 --------- .../Api/GraphQL/Models/Activity.cs | 30 +++ .../Api/GraphQL/Models/FileUpload.cs | 6 - src/Speckle.Sdk/Api/GraphQL/Models/User.cs | 12 -- src/Speckle.Sdk/Api/Helpers.cs | 122 ----------- .../Api/Operations/Operations.Receive.cs | 2 +- .../Api/Operations/Operations.Serialize.cs | 3 +- src/Speckle.Sdk/Common/Exceptions.cs | 2 - src/Speckle.Sdk/Common/HashCode.cs | 41 ++-- src/Speckle.Sdk/Credentials/AccountManager.cs | 42 ++-- .../Credentials/AuthFlowException.cs | 12 ++ src/Speckle.Sdk/Credentials/Exceptions.cs | 2 - src/Speckle.Sdk/Credentials/Responses.cs | 23 --- src/Speckle.Sdk/Credentials/StreamWrapper.cs | 9 +- src/Speckle.Sdk/Helpers/Http.cs | 9 +- .../Helpers/SpeckleHttpClientHandler.cs | 6 +- src/Speckle.Sdk/Helpers/State.cs | 87 -------- src/Speckle.Sdk/Host/Attributes.cs | 16 +- src/Speckle.Sdk/Host/TypeLoader.cs | 8 +- src/Speckle.Sdk/Logging/Analytics.cs | 12 +- src/Speckle.Sdk/Models/ApplicationObject.cs | 138 ------------- src/Speckle.Sdk/Models/Attributes.cs | 10 +- src/Speckle.Sdk/Models/Base.cs | 10 +- src/Speckle.Sdk/Models/Blob.cs | 3 +- .../Models/DeprecatedSpeckleTypeAttribute.cs | 5 +- src/Speckle.Sdk/Models/DynamicBase.cs | 9 +- .../Models/DynamicBaseMemberType.cs | 6 +- src/Speckle.Sdk/Models/Extras.cs | 11 +- .../Models/GraphTraversal/GraphTraversal.cs | 76 +++---- .../Models/InvalidPropNameException.cs | 2 - .../Models/SpeckleTypeAttribute.cs | 5 +- .../Serialisation/BaseObjectDeserializerV2.cs | 0 .../SpeckleDeserializeException.cs | 6 +- .../SpeckleObjectDeserializer.cs | 2 +- .../Serialisation/SpeckleObjectSerializer.cs | 18 +- .../SpeckleSerializerException.cs | 6 +- .../Serialisation/Utilities/ClosureParser.cs | 2 +- .../Serialisation/Utilities/ValueConverter.cs | 13 +- src/Speckle.Sdk/Setup.cs | 3 +- src/Speckle.Sdk/Transports/Exceptions.cs | 2 - src/Speckle.Sdk/Transports/Memory.cs | 3 +- src/Speckle.Sdk/Transports/SQLite.cs | 3 +- .../ServerUtils/ParallelServerAPI.cs | 2 - .../Transports/ServerUtils/ProgressContent.cs | 2 +- .../Transports/ServerUtils/ProgressStream.cs | 9 +- .../Transports/ServerUtils/ServerAPI.cs | 25 +-- src/Speckle.Sdk/Transports/ServerV2.cs | 4 +- tests/Speckle.LongSendProblem/Program.cs | 12 +- .../ModelPropertySupportedTypes.cs | 6 +- .../Api/GraphQL/Legacy/LegacyAPITests.cs | 16 -- .../GraphQL/Legacy/Subscriptions/Branches.cs | 131 ------------ .../GraphQL/Legacy/Subscriptions/Commits.cs | 168 ---------------- .../GraphQL/Legacy/Subscriptions/Streams.cs | 122 ----------- .../Benchmarks/GeneralDeserializerTest.cs | 2 +- .../Speckle.Sdk.Tests.Performance.csproj | 1 + .../TestDataHelper.cs | 1 - .../Api/Operations/SerializationTests.cs | 6 +- .../Host/HostApplicationTests.cs | 6 +- 96 files changed, 438 insertions(+), 1685 deletions(-) create mode 100644 CodeMetricsConfig.txt create mode 100644 Directory.Build.targets delete mode 100644 src/Speckle.Sdk/Api/GraphQL/Legacy/Manager.cs create mode 100644 src/Speckle.Sdk/Api/GraphQL/Models/Activity.cs create mode 100644 src/Speckle.Sdk/Credentials/AuthFlowException.cs delete mode 100644 src/Speckle.Sdk/Helpers/State.cs delete mode 100644 src/Speckle.Sdk/Models/ApplicationObject.cs create mode 100644 src/Speckle.Sdk/Serialisation/BaseObjectDeserializerV2.cs delete mode 100644 tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Branches.cs delete mode 100644 tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Commits.cs delete mode 100644 tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Streams.cs diff --git a/.editorconfig b/.editorconfig index 140ceb7d..7609a88d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -212,6 +212,7 @@ dotnet_diagnostic.ide0058.severity = none # Remove unnecessary expression value: dotnet_diagnostic.ide0010.severity = none # Add missing cases to switch statement: Too verbose dotnet_diagnostic.ide0200.severity = none # Remove unnecessary lambda expression: may be performance reasons not to dotnet_diagnostic.ide0058.severity = none # Remove unnecessary expression value: Subjective +dotnet_diagnostic.ide0305.severity = none # Use collection expression for fluent: Can obfuscate intent dotnet_diagnostic.ide0001.severity = suggestion # Name can be simplified: Non enforceable in build dotnet_diagnostic.ide0046.severity = suggestion # Use conditional expression for return: Subjective dotnet_diagnostic.ide0045.severity = suggestion # Use conditional expression for assignment: Subjective @@ -233,6 +234,17 @@ dotnet_diagnostic.ide0042.severity = suggestion # Deconstruct variable declarati dotnet_diagnostic.ide0028.severity = suggestion # Use collection initializers: Subjective dotnet_diagnostic.ide0072.severity = suggestion # Populate switch statement: Subjective dotnet_diagnostic.ide0074.severity = suggestion # Use compound assignment: Subjective +dotnet_diagnostic.ide0300.severity = suggestion # Use collection expression for array: Subjective, maybe aspirational +dotnet_diagnostic.ide0290.severity = suggestion # primary constructors: subjective, and readonly properties are not a thing +dotnet_diagnostic.ide0290.severity = suggestion # Use primary constructor: Subjective +dotnet_diagnostic.ide0037.severity = suggestion # Use inferred member names: Sometimes its nice to be explicit +dotnet_diagnostic.ide0301.severity = suggestion # Use collection expression for empty: Subjective, intent +dotnet_diagnostic.ide0021.severity = suggestion # Use expression body for constructors : Subjective +dotnet_diagnostic.ide0090.severity = suggestion # Simplify new expression : Subjective + +dotnet_diagnostic.ide0047.severity = suggestion # Parentheses preferences: IDEs don't properly pick it up +dotnet_diagnostic.ide0130.severity = suggestion # Namespace does not match folder structure : Aspirational +dotnet_diagnostic.ide1006.severity = suggestion # Naming rule violation : Aspirational # Maintainability rules dotnet_diagnostic.ca1501.severity = warning # Avoid excessive inheritance diff --git a/CodeMetricsConfig.txt b/CodeMetricsConfig.txt new file mode 100644 index 00000000..e69bf234 --- /dev/null +++ b/CodeMetricsConfig.txt @@ -0,0 +1,4 @@ +CA1502: 25 +CA1501: 5 +CA1506(Method): 50 +CA1506(Type): 95 diff --git a/Directory.Build.props b/Directory.Build.props index aef6ebeb..ed5b5fae 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,17 +6,9 @@ - latest + 12 enable enable - Recommended - true - true - true - true - true - False - False true true false @@ -25,6 +17,36 @@ true + + + true + latest-AllEnabledByDefault + true + true + false + true + + + + + CA5399;CA1812; + + CS1591;CS1573; + + CA1303;CA1304;CA1305;CA1307;CA1308;CA1309;CA1310;CA1311; + + CA1848;CA2254;CA1727; + + CA1815;CA1725; + + CA1710;CA1711;CA1724;CA1716;CA1720;CA1724; + + CA1502; + $(NoWarn) + + + + true @@ -39,8 +61,6 @@ true README.md Apache-2.0 - true - $(NoWarn);1591;1573 @@ -51,4 +71,11 @@ PackagePath="\" Visible="false"/> + + + + + + diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 00000000..4e66cb1e --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,14 @@ + + + Recommended + + $(NoWarn); + + CS0618;CA1034;CA2201;CA1051;CA1040;CA1724; + IDE0044;IDE0130;CA1508; + + CA5394;CA2007;CA1852;CA1819;CA1711;CA1063;CA1816;CA2234;CS8618;CA1054;CA1810;CA2208;CA1019; + + false + + diff --git a/Speckle.Sdk.sln b/Speckle.Sdk.sln index 67303822..b2d90631 100644 --- a/Speckle.Sdk.sln +++ b/Speckle.Sdk.sln @@ -22,6 +22,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{DA2AED README.md = README.md GitVersion.yml = GitVersion.yml docker-compose.yml = docker-compose.yml + CodeMetricsConfig.txt = CodeMetricsConfig.txt + Directory.Build.Targets = Directory.Build.Targets EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{58D37DA9-F948-48CA-9A73-F5BBBD533DBF}" diff --git a/build/Program.cs b/build/Program.cs index 0cd07382..b5e738ae 100644 --- a/build/Program.cs +++ b/build/Program.cs @@ -65,7 +65,7 @@ void RemoveDirectory(string d) DependsOn(RESTORE), async () => { - await RunAsync("dotnet", $"build Speckle.Sdk.sln -c Release --no-restore"); + await RunAsync("dotnet", $"build Speckle.Sdk.sln -c Release --no-restore").ConfigureAwait(false); } ); @@ -76,9 +76,11 @@ void RemoveDirectory(string d) async file => { await RunAsync( - "dotnet", - $"test {file} -c Release --no-build --no-restore --verbosity=normal /p:AltCover=true /p:AltCoverAttributeFilter=ExcludeFromCodeCoverage /p:AltCoverVerbosity=Warning" - ); + "dotnet", + $"test {file} -c Release --no-build --no-restore --verbosity=normal /p:AltCover=true /p:AltCoverAttributeFilter=ExcludeFromCodeCoverage /p:AltCoverVerbosity=Warning" + ) + .ConfigureAwait(false); + ; } ); @@ -87,15 +89,18 @@ await RunAsync( DependsOn(BUILD), async () => { - await RunAsync("docker", "compose -f docker-compose.yml up --wait"); + await RunAsync("docker", "compose -f docker-compose.yml up --wait").ConfigureAwait(false); + ; foreach (var test in Glob.Files(".", "**/*.Tests.Integration.csproj")) { await RunAsync( - "dotnet", - $"test {test} -c Release --no-build --no-restore --verbosity=normal /p:AltCover=true /p:AltCoverAttributeFilter=ExcludeFromCodeCoverage" - ); + "dotnet", + $"test {test} -c Release --no-build --no-restore --verbosity=normal /p:AltCover=true /p:AltCoverAttributeFilter=ExcludeFromCodeCoverage" + ) + .ConfigureAwait(false); + ; } - await RunAsync("docker", "compose down"); + await RunAsync("docker", "compose down").ConfigureAwait(false); } ); diff --git a/src/Speckle.Objects/BuiltElements/Rebar.cs b/src/Speckle.Objects/BuiltElements/Rebar.cs index 94d54603..6926a7d9 100644 --- a/src/Speckle.Objects/BuiltElements/Rebar.cs +++ b/src/Speckle.Objects/BuiltElements/Rebar.cs @@ -9,11 +9,8 @@ namespace Speckle.Objects.BuiltElements; /// /// This class is not suitable for freeform rebar, which can have multiple shapes. /// -public abstract class RebarGroup : Base, IHasVolume, IDisplayValue> - where T : RebarShape +public abstract class RebarGroup : Base, IHasVolume, IDisplayValue> { - public RebarGroup() { } - /// /// The shape of the rebar group /// diff --git a/src/Speckle.Objects/BuiltElements/Revit/FreeformElement.cs b/src/Speckle.Objects/BuiltElements/Revit/FreeformElement.cs index 6ba44237..ab7e4076 100644 --- a/src/Speckle.Objects/BuiltElements/Revit/FreeformElement.cs +++ b/src/Speckle.Objects/BuiltElements/Revit/FreeformElement.cs @@ -24,7 +24,7 @@ public FreeformElement(List baseGeometries, string subcategory = "", List< this.subcategory = subcategory; if (!IsValid()) { - throw new Exception("Freeform elements can only be created from BREPs or Meshes"); + throw new ArgumentException("Freeform elements can only be created from BREPs or Meshes", nameof(baseGeometries)); } this.parameters = parameters?.ToBase(); diff --git a/src/Speckle.Objects/BuiltElements/Revit/RevitOpening.cs b/src/Speckle.Objects/BuiltElements/Revit/RevitOpening.cs index d9340c10..6ffe022e 100644 --- a/src/Speckle.Objects/BuiltElements/Revit/RevitOpening.cs +++ b/src/Speckle.Objects/BuiltElements/Revit/RevitOpening.cs @@ -2,7 +2,6 @@ using Speckle.Objects.Utils; using Speckle.Sdk; using Speckle.Sdk.Host; -using Speckle.Sdk.Logging; using Speckle.Sdk.Models; namespace Speckle.Objects.BuiltElements.Revit; diff --git a/src/Speckle.Objects/BuiltElements/Revit/RevitRebar.cs b/src/Speckle.Objects/BuiltElements/Revit/RevitRebar.cs index f542496c..2df5b274 100644 --- a/src/Speckle.Objects/BuiltElements/Revit/RevitRebar.cs +++ b/src/Speckle.Objects/BuiltElements/Revit/RevitRebar.cs @@ -5,7 +5,7 @@ namespace Speckle.Objects.BuiltElements.Revit; [SpeckleType("Objects.BuiltElements.Revit.RevitRebarGroup")] -public class RevitRebarGroup : RebarGroup +public class RevitRebarGroup : RebarGroup { public RevitRebarGroup() { } diff --git a/src/Speckle.Objects/BuiltElements/Revit/RevitWall.cs b/src/Speckle.Objects/BuiltElements/Revit/RevitWall.cs index e024b391..cd12d816 100644 --- a/src/Speckle.Objects/BuiltElements/Revit/RevitWall.cs +++ b/src/Speckle.Objects/BuiltElements/Revit/RevitWall.cs @@ -147,13 +147,14 @@ public RevitFaceWall( { if (surface.Surfaces.Count == 0) { - throw new Exception("Cannot create a RevitWall with an empty BREP"); + throw new ArgumentException("Cannot create a RevitWall with an empty BREP", nameof(surface)); } if (surface.Surfaces.Count > 1) { - throw new Exception( - "The provided brep has more than 1 surface. Please deconstruct/explode it to create multiple instances" + throw new ArgumentException( + "The provided brep has more than 1 surface. Please deconstruct/explode it to create multiple instances", + nameof(surface) ); } diff --git a/src/Speckle.Objects/EncodingOptimisations.cs b/src/Speckle.Objects/EncodingOptimisations.cs index c6203993..d48792f4 100644 --- a/src/Speckle.Objects/EncodingOptimisations.cs +++ b/src/Speckle.Objects/EncodingOptimisations.cs @@ -18,7 +18,7 @@ public static class CurveTypeEncoding /// public static class CurveArrayEncodingExtensions { - public static List ToArray(List curves) + public static List ToArray(IReadOnlyCollection curves) { var list = new List(); foreach (var curve in curves) @@ -47,7 +47,7 @@ public static List ToArray(List curves) list.AddRange(p.ToList()); break; default: - throw new Exception($"Unkown curve type: {curve.GetType()}."); + throw new ArgumentOutOfRangeException(nameof(curves), $"Unkown curve type: {curve.GetType()}."); } } diff --git a/src/Speckle.Objects/GIS/GisPointFeature.cs b/src/Speckle.Objects/GIS/GisPointFeature.cs index 57fea198..57493268 100644 --- a/src/Speckle.Objects/GIS/GisPointFeature.cs +++ b/src/Speckle.Objects/GIS/GisPointFeature.cs @@ -12,8 +12,8 @@ public class GisPointFeature : Base, IGisFeature, IDisplayValue> [JsonIgnore] public required List geometry { - get { return displayValue; } - set { displayValue = value; } + get => displayValue; + set => displayValue = value; } [DetachProperty] diff --git a/src/Speckle.Objects/GIS/GisPolylineFeature.cs b/src/Speckle.Objects/GIS/GisPolylineFeature.cs index dc31bce7..2f4b578d 100644 --- a/src/Speckle.Objects/GIS/GisPolylineFeature.cs +++ b/src/Speckle.Objects/GIS/GisPolylineFeature.cs @@ -12,8 +12,8 @@ public class GisPolylineFeature : Base, IGisFeature, IDisplayValue geometry { - get { return displayValue; } - set { displayValue = value; } + get => displayValue; + set => displayValue = value; } [DetachProperty] diff --git a/src/Speckle.Objects/Geometry/Arc.cs b/src/Speckle.Objects/Geometry/Arc.cs index 9765670f..65fb376d 100644 --- a/src/Speckle.Objects/Geometry/Arc.cs +++ b/src/Speckle.Objects/Geometry/Arc.cs @@ -2,7 +2,6 @@ using Speckle.Objects.Primitive; using Speckle.Sdk; using Speckle.Sdk.Common; -using Speckle.Sdk.Logging; using Speckle.Sdk.Models; namespace Speckle.Objects.Geometry; @@ -293,7 +292,7 @@ public static Arc FromList(List list) endAngle = list[4], angleRadians = list[5], domain = new Interval { start = list[6], end = list[7] }, - units = Units.GetUnitFromEncoding(list[list.Count - 1]), + units = Units.GetUnitFromEncoding(list[^1]), plane = Plane.FromList(list.GetRange(8, 13)) }; arc.startPoint = Point.FromList(list.GetRange(21, 3), arc.units); diff --git a/src/Speckle.Objects/Geometry/Circle.cs b/src/Speckle.Objects/Geometry/Circle.cs index 776dd083..2d447453 100644 --- a/src/Speckle.Objects/Geometry/Circle.cs +++ b/src/Speckle.Objects/Geometry/Circle.cs @@ -74,7 +74,7 @@ public static Circle FromList(List list) radius = list[2], domain = new Interval { start = list[3], end = list[4] }, plane = Plane.FromList(list.GetRange(5, 13)), - units = Units.GetUnitFromEncoding(list[list.Count - 1]) + units = Units.GetUnitFromEncoding(list[^1]) }; return circle; diff --git a/src/Speckle.Objects/Geometry/Ellipse.cs b/src/Speckle.Objects/Geometry/Ellipse.cs index 37d4b394..029eb5d9 100644 --- a/src/Speckle.Objects/Geometry/Ellipse.cs +++ b/src/Speckle.Objects/Geometry/Ellipse.cs @@ -69,7 +69,7 @@ public static Ellipse FromList(List list) secondRadius = list[3], domain = new Interval { start = list[4], end = list[5] }, plane = Plane.FromList(list.GetRange(6, 13)), - units = Units.GetUnitFromEncoding(list[list.Count - 1]) + units = Units.GetUnitFromEncoding(list[^1]) }; return ellipse; } diff --git a/src/Speckle.Objects/Geometry/Line.cs b/src/Speckle.Objects/Geometry/Line.cs index b4b6c8f1..acfb224d 100644 --- a/src/Speckle.Objects/Geometry/Line.cs +++ b/src/Speckle.Objects/Geometry/Line.cs @@ -3,7 +3,6 @@ using Speckle.Objects.Primitive; using Speckle.Sdk; using Speckle.Sdk.Common; -using Speckle.Sdk.Logging; using Speckle.Sdk.Models; namespace Speckle.Objects.Geometry; @@ -121,9 +120,9 @@ public List ToList() return list; } - public static Line FromList(List list) + public static Line FromList(IReadOnlyList list) { - var units = Units.GetUnitFromEncoding(list[list.Count - 1]); + var units = Units.GetUnitFromEncoding(list[^1]); var startPt = new Point(list[2], list[3], list[4], units); var endPt = new Point(list[5], list[6], list[7], units); var line = new Line(startPt, endPt, units) diff --git a/src/Speckle.Objects/Geometry/Mesh.cs b/src/Speckle.Objects/Geometry/Mesh.cs index 0b12498d..c6b96871 100644 --- a/src/Speckle.Objects/Geometry/Mesh.cs +++ b/src/Speckle.Objects/Geometry/Mesh.cs @@ -2,7 +2,6 @@ using Speckle.Objects.Other; using Speckle.Sdk; using Speckle.Sdk.Common; -using Speckle.Sdk.Logging; using Speckle.Sdk.Models; namespace Speckle.Objects.Geometry; diff --git a/src/Speckle.Objects/Geometry/Plane.cs b/src/Speckle.Objects/Geometry/Plane.cs index d270c3ef..c119b067 100644 --- a/src/Speckle.Objects/Geometry/Plane.cs +++ b/src/Speckle.Objects/Geometry/Plane.cs @@ -87,9 +87,9 @@ public List ToList() /// /// The list of values representing this plane /// A new with the provided values. - public static Plane FromList(List list) + public static Plane FromList(IReadOnlyList list) { - var units = Units.GetUnitFromEncoding(list[list.Count - 1]); + var units = Units.GetUnitFromEncoding(list[^1]); var plane = new Plane { origin = new Point(list[0], list[1], list[2], units), diff --git a/src/Speckle.Objects/Geometry/Point.cs b/src/Speckle.Objects/Geometry/Point.cs index 24ea8673..1773212c 100644 --- a/src/Speckle.Objects/Geometry/Point.cs +++ b/src/Speckle.Objects/Geometry/Point.cs @@ -216,14 +216,14 @@ public double DistanceTo(Point point) return Math.Sqrt(Math.Pow(x - point.x, 2) + Math.Pow(y - point.y, 2) + Math.Pow(z - point.z, 2)); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } - if (ReferenceEquals(obj, null)) + if (obj is null) { return false; } diff --git a/src/Speckle.Objects/Geometry/Pointcloud.cs b/src/Speckle.Objects/Geometry/Pointcloud.cs index 30969db9..4852c5c5 100644 --- a/src/Speckle.Objects/Geometry/Pointcloud.cs +++ b/src/Speckle.Objects/Geometry/Pointcloud.cs @@ -2,7 +2,6 @@ using Speckle.Sdk; using Speckle.Sdk.Common; using Speckle.Sdk.Host; -using Speckle.Sdk.Logging; using Speckle.Sdk.Models; namespace Speckle.Objects.Geometry; diff --git a/src/Speckle.Objects/Geometry/Surface.cs b/src/Speckle.Objects/Geometry/Surface.cs index 896b7988..fa2ac70f 100644 --- a/src/Speckle.Objects/Geometry/Surface.cs +++ b/src/Speckle.Objects/Geometry/Surface.cs @@ -250,7 +250,7 @@ public static Surface FromList(List list) srf.knotsU = list.GetRange(14 + pointCount, knotsUCount); srf.knotsV = list.GetRange(14 + pointCount + knotsUCount, knotsVCount); - var u = list[list.Count - 1]; + var u = list[^1]; srf.units = Units.GetUnitFromEncoding(u); return srf; } diff --git a/src/Speckle.Objects/Other/Transform.cs b/src/Speckle.Objects/Other/Transform.cs index 5f6f75fd..02d69575 100644 --- a/src/Speckle.Objects/Other/Transform.cs +++ b/src/Speckle.Objects/Other/Transform.cs @@ -3,7 +3,6 @@ using Speckle.Objects.Geometry; using Speckle.Sdk; using Speckle.Sdk.Common; -using Speckle.Sdk.Logging; using Speckle.Sdk.Models; using Vector = Speckle.Objects.Geometry.Vector; diff --git a/src/Speckle.Objects/Speckle.Objects.csproj b/src/Speckle.Objects/Speckle.Objects.csproj index 69da17a1..8ee3ceb7 100644 --- a/src/Speckle.Objects/Speckle.Objects.csproj +++ b/src/Speckle.Objects/Speckle.Objects.csproj @@ -13,6 +13,13 @@ snupkg + + + $(NoWarn); + IDE0060;CA1034;CA1819;CA1708;CA1008;CA2225;CA1024; + + + diff --git a/src/Speckle.Sdk.Logging/Consts.cs b/src/Speckle.Sdk.Logging/Consts.cs index 833d694e..882153b2 100644 --- a/src/Speckle.Sdk.Logging/Consts.cs +++ b/src/Speckle.Sdk.Logging/Consts.cs @@ -33,6 +33,6 @@ public static string GetPackageVersion(this Assembly assembly) } var indexOfPlusSign = informationalVersion.IndexOf('+'); - return indexOfPlusSign > 0 ? informationalVersion.Substring(0, indexOfPlusSign) : informationalVersion; + return indexOfPlusSign > 0 ? informationalVersion[..indexOfPlusSign] : informationalVersion; } } diff --git a/src/Speckle.Sdk.Logging/ISpeckleLogger.cs b/src/Speckle.Sdk.Logging/ISpeckleLogger.cs index 6df70b7a..3df1a4af 100644 --- a/src/Speckle.Sdk.Logging/ISpeckleLogger.cs +++ b/src/Speckle.Sdk.Logging/ISpeckleLogger.cs @@ -6,14 +6,14 @@ public interface ISpeckleLogger void Write(SpeckleLogLevel speckleLogLevel, Exception? exception, string message, params object?[] arguments); void Debug(string message, params object?[] arguments); - void Debug(Exception exception, string message, params object?[] arguments); + void Debug(Exception? exception, string message, params object?[] arguments); void Warning(string message, params object?[] arguments); - void Warning(Exception exception, string message, params object?[] arguments); + void Warning(Exception? exception, string message, params object?[] arguments); void Information(string message, params object?[] arguments); - void Information(Exception exception, string message, params object?[] arguments); + void Information(Exception? exception, string message, params object?[] arguments); void Error(string message, params object?[] arguments); - void Error(Exception exception, string message, params object?[] arguments); - void Fatal(Exception exception, string message, params object?[] arguments); + void Error(Exception? exception, string message, params object?[] arguments); + void Fatal(Exception? exception, string message, params object?[] arguments); } diff --git a/src/Speckle.Sdk.Logging/SpeckleActivity.cs b/src/Speckle.Sdk.Logging/SpeckleActivity.cs index 7312f382..0f992583 100644 --- a/src/Speckle.Sdk.Logging/SpeckleActivity.cs +++ b/src/Speckle.Sdk.Logging/SpeckleActivity.cs @@ -3,7 +3,7 @@ namespace Speckle.Sdk.Logging; -public class SpeckleActivity(Activity activity) : ISpeckleActivity +public sealed class SpeckleActivity(Activity activity) : ISpeckleActivity { public void Dispose() => activity.Dispose(); diff --git a/src/Speckle.Sdk.Logging/SpeckleLogger.cs b/src/Speckle.Sdk.Logging/SpeckleLogger.cs index 5b83eff2..326fb238 100644 --- a/src/Speckle.Sdk.Logging/SpeckleLogger.cs +++ b/src/Speckle.Sdk.Logging/SpeckleLogger.cs @@ -3,7 +3,7 @@ namespace Speckle.Sdk.Logging; -internal class SpeckleLogger : ISpeckleLogger +internal sealed class SpeckleLogger : ISpeckleLogger { private readonly Serilog.ILogger _logger; @@ -36,24 +36,24 @@ params object?[] arguments public void Debug(string message, params object?[] arguments) => _logger.Debug(message, arguments); - public void Debug(Exception exception, string message, params object?[] arguments) => + public void Debug(Exception? exception, string message, params object?[] arguments) => _logger.Debug(exception, message, arguments); public void Warning(string message, params object?[] arguments) => _logger.Warning(message, arguments); - public void Warning(Exception exception, string message, params object?[] arguments) => + public void Warning(Exception? exception, string message, params object?[] arguments) => _logger.Warning(exception, message, arguments); public void Information(string message, params object?[] arguments) => _logger.Information(message, arguments); - public void Information(Exception exception, string message, params object?[] arguments) => + public void Information(Exception? exception, string message, params object?[] arguments) => _logger.Information(exception, message, arguments); public void Error(string message, params object?[] arguments) => _logger.Error(message, arguments); - public void Error(Exception exception, string message, params object?[] arguments) => + public void Error(Exception? exception, string message, params object?[] arguments) => _logger.Error(exception, message, arguments); - public void Fatal(Exception exception, string message, params object?[] arguments) => + public void Fatal(Exception? exception, string message, params object?[] arguments) => _logger.Fatal(exception, message, arguments); } diff --git a/src/Speckle.Sdk/Api/Exceptions.cs b/src/Speckle.Sdk/Api/Exceptions.cs index 165a086b..5be89d06 100644 --- a/src/Speckle.Sdk/Api/Exceptions.cs +++ b/src/Speckle.Sdk/Api/Exceptions.cs @@ -1,5 +1,4 @@ using GraphQL; -using Speckle.Sdk.Logging; namespace Speckle.Sdk.Api; diff --git a/src/Speckle.Sdk/Api/GraphQL/Client.cs b/src/Speckle.Sdk/Api/GraphQL/Client.cs index d187eae6..01aa0a61 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Client.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Client.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Net.WebSockets; using System.Reflection; @@ -16,6 +16,7 @@ namespace Speckle.Sdk.Api; +[SuppressMessage("Maintainability", "CA1506:Avoid excessive class coupling", Justification = "Class needs refactor")] public sealed partial class Client : ISpeckleGraphQLClient, IDisposable { public ProjectResource Project { get; } @@ -27,11 +28,7 @@ public sealed partial class Client : ISpeckleGraphQLClient, IDisposable public CommentResource Comment { get; } public SubscriptionResource Subscription { get; } - public string ServerUrl => Account.serverInfo.url; - - public string ApiToken => Account.token; - - public System.Version? ServerVersion { get; private set; } + public Uri ServerUrl => new(Account.serverInfo.url); [JsonIgnore] public Account Account { get; } @@ -65,16 +62,6 @@ public void Dispose() try { Subscription.Dispose(); - UserStreamAddedSubscription?.Dispose(); - UserStreamRemovedSubscription?.Dispose(); - StreamUpdatedSubscription?.Dispose(); - BranchCreatedSubscription?.Dispose(); - BranchUpdatedSubscription?.Dispose(); - BranchDeletedSubscription?.Dispose(); - CommitCreatedSubscription?.Dispose(); - CommitUpdatedSubscription?.Dispose(); - CommitDeletedSubscription?.Dispose(); - CommentActivitySubscription?.Dispose(); GQLClient.Dispose(); } catch (Exception ex) when (!ex.IsFatal()) { } @@ -174,9 +161,9 @@ internal void MaybeThrowFromGraphQLErrors(GraphQLRequest request, GraphQLResp private Dictionary ConvertExpandoToDict(ExpandoObject expando) { var variables = new Dictionary(); - foreach (KeyValuePair kvp in expando) + foreach (KeyValuePair kvp in expando) { - object value; + object? value; if (kvp.Value is ExpandoObject ex) { value = ConvertExpandoToDict(ex); diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ActivityOperations.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ActivityOperations.cs index daa3130b..e2d6ece1 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ActivityOperations.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ActivityOperations.cs @@ -1,4 +1,5 @@ using GraphQL; +using Speckle.Sdk.Api.GraphQL.Models; namespace Speckle.Sdk.Api; @@ -16,7 +17,7 @@ public partial class Client /// Max number of activity items to get /// /// - public async Task> StreamGetActivity( + public async Task> StreamGetActivity( string id, DateTime? after = null, DateTime? before = null, diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ServerOperations.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ServerOperations.cs index 702353bf..fb5b9cf5 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ServerOperations.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.ServerOperations.cs @@ -1,7 +1,6 @@ using System.Text.RegularExpressions; using GraphQL; using Speckle.Sdk.Api.GraphQL.Models.Responses; -using Speckle.Sdk.Logging; namespace Speckle.Sdk.Api; @@ -33,7 +32,7 @@ public partial class Client return new System.Version(999, 999, 999); } - ServerVersion = new System.Version(Regex.Replace(res.serverInfo.version, "[-a-zA-Z]+", "")); - return ServerVersion; + var serverVersion = new System.Version(Regex.Replace(res.serverInfo.version, "[-a-zA-Z]+", "")); + return serverVersion; } } diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.StreamOperations.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.StreamOperations.cs index aaeaec32..e4c1631a 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.StreamOperations.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.GraphqlCleintOperations/Client.StreamOperations.cs @@ -1,9 +1,7 @@ #nullable disable using GraphQL; using Speckle.Sdk.Api.GraphQL.Models; -using Speckle.Sdk.Api.GraphQL.Models.Responses; using Speckle.Sdk.Api.GraphQL.Resources; -using Speckle.Sdk.Logging; namespace Speckle.Sdk.Api; @@ -96,168 +94,26 @@ public async Task StreamGet(string id, int branchesLimit = 10, Cancellat return (await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false)).stream; } - /// - /// Gets all streams for the current user - /// - /// Max number of streams to return - /// - /// - /// - [Obsolete($"Use client.{nameof(ActiveUser)}.{nameof(ActiveUserResource.GetProjects)}")] - public async Task> StreamsGet(int limit = 10, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = - $@"query User {{ - activeUser{{ - id, - email, - name, - bio, - company, - avatar, - verified, - profiles, - role, - streams(limit:{limit}) {{ - totalCount, - cursor, - items {{ - id, - name, - description, - isPublic, - role, - createdAt, - updatedAt, - favoritedDate, - commentCount - favoritesCount - collaborators {{ - id, - name, - role, - avatar - }} - }} - }} - }} - }}" - }; - - var res = await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false); - - if (res?.activeUser == null) - { - throw new SpeckleException( - "User is not authenticated, or the credentials were not valid. Check the provided account is still valid, remove it from manager and add it again." - ); - } - - return res.activeUser.streams.items; - } - - //TODO: API GAP /// /// Gets all favorite streams for the current user /// /// Max number of streams to return /// /// - public async Task> FavoriteStreamsGet(int limit = 10, CancellationToken cancellationToken = default) - { - var request = new GraphQLRequest - { - Query = - $@"query User {{ - activeUser{{ - id, - email, - name, - bio, - company, - avatar, - verified, - profiles, - role, - favoriteStreams(limit:{limit}) {{ - totalCount, - cursor, - items {{ - id, - name, - description, - isPublic, - role, - createdAt, - updatedAt, - favoritedDate, - commentCount - favoritesCount - collaborators {{ - id, - name, - role, - avatar - }} - }} - }} - }} - }}" - }; - return (await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false)) - .activeUser - .favoriteStreams - .items; - } + [Obsolete("Favourite streams are no longer a supported feature", true)] + public Task> FavoriteStreamsGet(int limit = 10, CancellationToken cancellationToken = default) => + throw new NotImplementedException(); /// - /// Searches the user's streams by name, description, and ID + /// Gets all streams for the current user /// - /// String query to search for /// Max number of streams to return /// /// - /// - [Obsolete($"Use client.{nameof(ActiveUser)}.{nameof(ActiveUserResource.GetProjects)}")] - public async Task> StreamSearch( - string query, - int limit = 10, - CancellationToken cancellationToken = default - ) - { - var request = new GraphQLRequest - { - Query = - @"query Streams ($query: String!, $limit: Int!) { - streams(query: $query, limit: $limit) { - totalCount, - cursor, - items { - id, - name, - description, - isPublic, - role, - createdAt, - updatedAt, - commentCount - favoritesCount - collaborators { - id, - name, - role - } - } - } - }", - Variables = new { query, limit } - }; - - var res = await GQLClient.SendMutationAsync(request, cancellationToken).ConfigureAwait(false); //WARN: Why do we do this? - return (await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false)).streams.items; - } + /// + [Obsolete($"Use client.{nameof(ActiveUser)}.{nameof(ActiveUserResource.GetProjects)}", true)] + public Task> StreamsGet(int limit = 10, CancellationToken cancellationToken = default) => + throw new NotImplementedException(); /// /// Creates a stream. @@ -378,33 +234,10 @@ mutation streamUpdatePermission($permissionParams: StreamUpdatePermissionInput!) /// /// /// - [Obsolete($"Use client.{nameof(Project)}.{nameof(ProjectResource.GetWithTeam)}")] - public async Task StreamGetPendingCollaborators( - string streamId, - CancellationToken cancellationToken = default - ) + [Obsolete($"Use client.{nameof(Project)}.{nameof(ProjectResource.GetWithTeam)}", true)] + public Task StreamGetPendingCollaborators(string streamId, CancellationToken cancellationToken = default) { - var request = new GraphQLRequest - { - Query = - @"query Stream($id: String!) { - stream(id: $id) { - id - pendingCollaborators { - id - inviteId - title - role - user { - avatar - } - } - } - }", - Variables = new { id = streamId } - }; - var res = await GQLClient.SendMutationAsync(request, cancellationToken).ConfigureAwait(false); //WARN: Why do we do this? - return (await ExecuteGraphQLRequest(request, cancellationToken).ConfigureAwait(false)).stream; + throw new NotImplementedException(); } /// diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Branch.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Branch.cs index 64510c81..95db13e8 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Branch.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Branch.cs @@ -1,85 +1,16 @@ #nullable disable -using GraphQL; +using Speckle.Sdk.Api.GraphQL.Resources; namespace Speckle.Sdk.Api; public partial class Client { - #region BranchCreated + [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectModelsUpdatedSubscription)}", true)] + public void SubscribeBranchCreated(string streamId) => throw new NotImplementedException(); - public delegate void BranchCreatedHandler(object sender, BranchInfo e); + [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectModelsUpdatedSubscription)}", true)] + public void SubscribeBranchUpdated(string streamId, string branchId = null) => throw new NotImplementedException(); - public event BranchCreatedHandler OnBranchCreated; - public IDisposable BranchCreatedSubscription { get; private set; } - - /// - /// Subscribe to events of branch created for a stream - /// - /// - public void SubscribeBranchCreated(string streamId) - { - var request = new GraphQLRequest { Query = $@"subscription {{ branchCreated (streamId: ""{streamId}"") }}" }; - - BranchCreatedSubscription = SubscribeTo( - request, - (sender, result) => OnBranchCreated?.Invoke(sender, result.branchCreated) - ); - } - - public bool HasSubscribedBranchCreated => BranchCreatedSubscription != null; - - #endregion - - - #region BranchUpdated - - public delegate void BranchUpdatedHandler(object sender, BranchInfo e); - - public event BranchUpdatedHandler OnBranchUpdated; - public IDisposable BranchUpdatedSubscription { get; private set; } - - /// - /// Subscribe to events of branch updated for a stream - /// - /// - public void SubscribeBranchUpdated(string streamId, string branchId = null) - { - var request = new GraphQLRequest - { - Query = $@"subscription {{ branchUpdated (streamId: ""{streamId}"", branchId: ""{branchId}"") }}" - }; - BranchUpdatedSubscription = SubscribeTo( - request, - (sender, result) => OnBranchUpdated?.Invoke(sender, result.branchUpdated) - ); - } - - public bool HasSubscribedBranchUpdated => BranchUpdatedSubscription != null; - - #endregion - - #region BranchDeleted - - public delegate void BranchDeletedHandler(object sender, BranchInfo e); - - public event BranchDeletedHandler OnBranchDeleted; - public IDisposable BranchDeletedSubscription { get; private set; } - - /// - /// Subscribe to events of branch deleted for a stream - /// - /// - public void SubscribeBranchDeleted(string streamId) - { - var request = new GraphQLRequest { Query = $@"subscription {{ branchDeleted (streamId: ""{streamId}"") }}" }; - - BranchDeletedSubscription = SubscribeTo( - request, - (sender, result) => OnBranchDeleted?.Invoke(sender, result.branchDeleted) - ); - } - - public bool HasSubscribedBranchDeleted => BranchDeletedSubscription != null; - - #endregion + [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectModelsUpdatedSubscription)}", true)] + public void SubscribeBranchDeleted(string streamId) => throw new NotImplementedException(); } diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Commit.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Commit.cs index 02b4817f..fa8d05ce 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Commit.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Commit.cs @@ -1,85 +1,25 @@ #nullable disable -using GraphQL; +using Speckle.Sdk.Api.GraphQL.Resources; namespace Speckle.Sdk.Api; public partial class Client { - #region CommitCreated - - public delegate void CommitCreatedHandler(object sender, CommitInfo e); - - public event CommitCreatedHandler OnCommitCreated; - public IDisposable CommitCreatedSubscription; - - /// - /// Subscribe to events of commit created for a stream - /// - /// - public void SubscribeCommitCreated(string streamId) - { - var request = new GraphQLRequest { Query = $@"subscription {{ commitCreated (streamId: ""{streamId}"") }}" }; - - CommitCreatedSubscription = SubscribeTo( - request, - (sender, result) => OnCommitCreated?.Invoke(sender, result.commitCreated) - ); - } - - public bool HasSubscribedCommitCreated => CommitCreatedSubscription != null; - - #endregion - - #region CommitUpdated - - public delegate void CommitUpdatedHandler(object sender, CommitInfo e); - - public event CommitUpdatedHandler OnCommitUpdated; - public IDisposable CommitUpdatedSubscription; - - /// - /// Subscribe to events of commit updated for a stream - /// - /// - public void SubscribeCommitUpdated(string streamId, string commitId = null) - { - var request = new GraphQLRequest - { - Query = $@"subscription {{ commitUpdated (streamId: ""{streamId}"", commitId: ""{commitId}"") }}" - }; - - var res = GQLClient.CreateSubscriptionStream(request); - CommitUpdatedSubscription = SubscribeTo( - request, - (sender, result) => OnCommitUpdated?.Invoke(sender, result.commitUpdated) - ); - } - - public bool HasSubscribedCommitUpdated => CommitUpdatedSubscription != null; - - #endregion - - #region CommitDeleted - - public delegate void CommitDeletedHandler(object sender, CommitInfo e); - - public event CommitDeletedHandler OnCommitDeleted; - public IDisposable CommitDeletedSubscription; - - /// - /// Subscribe to events of commit updated for a stream - /// - /// - public void SubscribeCommitDeleted(string streamId) - { - var request = new GraphQLRequest { Query = $@"subscription {{ commitDeleted (streamId: ""{streamId}"") }}" }; - CommitDeletedSubscription = SubscribeTo( - request, - (sender, result) => OnCommitDeleted?.Invoke(sender, result.commitDeleted) - ); - } - - public bool HasSubscribedCommitDeleted => CommitDeletedSubscription != null; - - #endregion + [Obsolete( + $"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectVersionsUpdatedSubscription)}", + true + )] + public void SubscribeCommitCreated(string streamId) => throw new NotImplementedException(); + + [Obsolete( + $"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectVersionsUpdatedSubscription)}", + true + )] + public void SubscribeCommitUpdated(string streamId, string commitId = null) => throw new NotImplementedException(); + + [Obsolete( + $"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectVersionsUpdatedSubscription)}", + true + )] + public void SubscribeCommitDeleted(string streamId) => throw new NotImplementedException(); } diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Stream.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Stream.cs index a969fc4d..d01eebe4 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Stream.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Legacy/Client.Subscriptions/Client.Subscriptions.Stream.cs @@ -1,108 +1,22 @@ #nullable disable -using GraphQL; +using Speckle.Sdk.Api.GraphQL.Resources; namespace Speckle.Sdk.Api; public partial class Client { - #region UserStreamAdded + [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateUserProjectsUpdatedSubscription)}", true)] + public void SubscribeUserStreamAdded() => throw new NotImplementedException(); - public delegate void UserStreamAddedHandler(object sender, StreamInfo e); + [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectUpdatedSubscription)}", true)] + public void SubscribeStreamUpdated(string id) => throw new NotImplementedException(); - public event UserStreamAddedHandler OnUserStreamAdded; - public IDisposable UserStreamAddedSubscription; + [Obsolete($"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateUserProjectsUpdatedSubscription)}", true)] + public void SubscribeUserStreamRemoved() => throw new NotImplementedException(); - /// - /// Subscribe to events of streams added for the current user - /// - /// - public void SubscribeUserStreamAdded() - { - var request = new GraphQLRequest { Query = @"subscription { userStreamAdded }" }; - - UserStreamAddedSubscription = SubscribeTo( - request, - (sender, result) => OnUserStreamAdded?.Invoke(sender, result.userStreamAdded) - ); - } - - public bool HasSubscribedUserStreamAdded => UserStreamAddedSubscription != null; - - #endregion - - #region StreamUpdated - - public delegate void StreamUpdatedHandler(object sender, StreamInfo e); - - public event StreamUpdatedHandler OnStreamUpdated; - public IDisposable StreamUpdatedSubscription; - - /// - /// Subscribe to events of streams updated for a specific streamId - /// - /// streamId - public void SubscribeStreamUpdated(string id) - { - var request = new GraphQLRequest { Query = $@"subscription {{ streamUpdated( streamId: ""{id}"") }}" }; - StreamUpdatedSubscription = SubscribeTo( - request, - (sender, result) => OnStreamUpdated?.Invoke(sender, result.streamUpdated) - ); - } - - public bool HasSubscribedStreamUpdated => StreamUpdatedSubscription != null; - - #endregion - - #region StreamRemoved - - public delegate void UserStreamRemovedHandler(object sender, StreamInfo e); - - public event UserStreamRemovedHandler OnUserStreamRemoved; - public IDisposable UserStreamRemovedSubscription; - - /// - /// Subscribe to events of streams removed for the current user - /// - public void SubscribeUserStreamRemoved() - { - var request = new GraphQLRequest { Query = @"subscription { userStreamRemoved }" }; - - UserStreamRemovedSubscription = SubscribeTo( - request, - (sender, result) => OnUserStreamRemoved?.Invoke(sender, result.userStreamRemoved) - ); - } - - public bool HasSubscribedUserStreamRemoved => UserStreamRemovedSubscription != null; - - #endregion - - #region CommentActivity - - public delegate void CommentActivityHandler(object sender, CommentItem e); - - public event CommentActivityHandler OnCommentActivity; - public IDisposable CommentActivitySubscription; - - /// - /// Subscribe to new comment events - /// - /// - public void SubscribeCommentActivity(string streamId) - { - var request = new GraphQLRequest - { - Query = - $@"subscription {{ commentActivity( streamId: ""{streamId}"") {{ type comment {{ id authorId archived screenshot rawText }} }} }}" - }; - CommentActivitySubscription = SubscribeTo( - request, - (sender, result) => OnCommentActivity?.Invoke(sender, result.commentActivity.comment) - ); - } - - public bool HasSubscribedCommentActivity => CommentActivitySubscription != null; - - #endregion + [Obsolete( + $"Use {nameof(Subscription)}.{nameof(SubscriptionResource.CreateProjectCommentsUpdatedSubscription)}", + true + )] + public void SubscribeCommentActivity(string streamId) => throw new NotImplementedException(); } diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/LegacyGraphQLModels.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/LegacyGraphQLModels.cs index 431943ce..f237341b 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/LegacyGraphQLModels.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Legacy/LegacyGraphQLModels.cs @@ -154,7 +154,7 @@ public class Stream /// public Commits commits { get; set; } - public Activity activity { get; set; } + public ResourceCollection activity { get; set; } public SpeckleObject @object { get; set; } @@ -222,40 +222,6 @@ public override string ToString() } } -public class Activity -{ - public int totalCount { get; set; } - public DateTime cursor { get; set; } - public List items { get; set; } -} - -public class ActivityItem -{ - public string actionType { get; set; } - public string userId { get; set; } - public string streamId { get; set; } - public string resourceId { get; set; } - public string resourceType { get; set; } - public DateTime time { get; set; } - public Info info { get; set; } - public string message { get; set; } -} - -public class Info -{ - public string message { get; set; } - public string sourceApplication { get; set; } - - public InfoCommit commit { get; set; } -} - -public class InfoCommit -{ - public string message { get; set; } - public string sourceApplication { get; set; } - public string branchName { get; set; } -} - [Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] public class SpeckleObject { diff --git a/src/Speckle.Sdk/Api/GraphQL/Legacy/Manager.cs b/src/Speckle.Sdk/Api/GraphQL/Legacy/Manager.cs deleted file mode 100644 index fe46ab7c..00000000 --- a/src/Speckle.Sdk/Api/GraphQL/Legacy/Manager.cs +++ /dev/null @@ -1,96 +0,0 @@ -#nullable disable -using System.Text.Json.Serialization; - -namespace Speckle.Sdk.Api; - -#region manager api - -public class Connector -{ - public List Versions { get; set; } = new(); -} - -public class ConnectorVersion -{ - public ConnectorVersion(string number, string url, Os os = Os.Win, Architecture architecture = Architecture.Any) - { - Number = number; - Url = url; - Date = DateTime.Now; - Prerelease = Number.Contains("-"); - Os = os; - Architecture = architecture; - } - - public string Number { get; set; } - public string Url { get; set; } - public Os Os { get; set; } - public Architecture Architecture { get; set; } = Architecture.Any; - public DateTime Date { get; set; } - - [JsonIgnore] - public string DateTimeAgo => Helpers.TimeAgo(Date); - - public bool Prerelease { get; set; } -} - -/// -/// OS -/// NOTE: do not edit order and only append new items as they are serialized to ints -/// -public enum Os -{ - Win, //0 - OSX, //1 - Linux, //2 - Any //3 -} - -/// -/// Architecture -/// NOTE: do not edit order and only append new items as they are serialized to ints -/// -public enum Architecture -{ - Any, //0 - Arm, //1 - Intel //2 -} - -//GHOST API -public class Meta -{ - public Pagination pagination { get; set; } -} - -public class Pagination -{ - public int page { get; set; } - public string limit { get; set; } - public int pages { get; set; } - public int total { get; set; } - public object next { get; set; } - public object prev { get; set; } -} - -public class Tags -{ - public List tags { get; set; } - public Meta meta { get; set; } -} - -public class Tag -{ - public string id { get; set; } - public string name { get; set; } - public string slug { get; set; } - public string description { get; set; } - public string feature_image { get; set; } - public string visibility { get; set; } - public string codeinjection_head { get; set; } - public object codeinjection_foot { get; set; } - public object canonical_url { get; set; } - public string accent_color { get; set; } - public string url { get; set; } -} -#endregion diff --git a/src/Speckle.Sdk/Api/GraphQL/Models/Activity.cs b/src/Speckle.Sdk/Api/GraphQL/Models/Activity.cs new file mode 100644 index 00000000..55d92532 --- /dev/null +++ b/src/Speckle.Sdk/Api/GraphQL/Models/Activity.cs @@ -0,0 +1,30 @@ +#nullable disable +namespace Speckle.Sdk.Api.GraphQL.Models; + +public sealed class Activity +{ + public string actionType { get; init; } + public string id { get; init; } + public Info info { get; init; } + public string message { get; init; } + public string resourceId { get; init; } + public string resourceType { get; init; } + public string streamId { get; init; } + public DateTime time { get; init; } + public string userId { get; init; } +} + +public sealed class Info +{ + public string message { get; init; } + public string sourceApplication { get; init; } + + public InfoCommit commit { get; init; } +} + +public sealed class InfoCommit +{ + public string message { get; init; } + public string sourceApplication { get; init; } + public string branchName { get; init; } +} diff --git a/src/Speckle.Sdk/Api/GraphQL/Models/FileUpload.cs b/src/Speckle.Sdk/Api/GraphQL/Models/FileUpload.cs index 4a6f3b53..f9c81ddc 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Models/FileUpload.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Models/FileUpload.cs @@ -20,10 +20,4 @@ public sealed class FileUpload public bool uploadComplete { get; init; } public DateTime uploadDate { get; init; } public string userId { get; init; } - - [Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] - public string branchName { get; init; } - - [Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] - public string streamId { get; init; } } diff --git a/src/Speckle.Sdk/Api/GraphQL/Models/User.cs b/src/Speckle.Sdk/Api/GraphQL/Models/User.cs index 7bc1d3da..59eab643 100644 --- a/src/Speckle.Sdk/Api/GraphQL/Models/User.cs +++ b/src/Speckle.Sdk/Api/GraphQL/Models/User.cs @@ -13,15 +13,6 @@ public abstract class UserBase public string role { get; init; } public ResourceCollection timeline { get; init; } public bool? verified { get; init; } - - [Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] - public int totalOwnedStreamsFavorites { get; init; } - - [Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] - public ResourceCollection commits { get; init; } - - [Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] - public ResourceCollection streams { get; init; } } public sealed class LimitedUser : UserBase @@ -41,9 +32,6 @@ public sealed class User : UserBase public List projectInvites { get; init; } public ResourceCollection projects { get; init; } - [Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] - public ResourceCollection favoriteStreams { get; init; } - public override string ToString() { return $"User ({email} | {name} | {id})"; diff --git a/src/Speckle.Sdk/Api/Helpers.cs b/src/Speckle.Sdk/Api/Helpers.cs index a0d1b038..98fb6c47 100644 --- a/src/Speckle.Sdk/Api/Helpers.cs +++ b/src/Speckle.Sdk/Api/Helpers.cs @@ -1,133 +1,11 @@ -using System.Collections.Concurrent; using System.Diagnostics.Contracts; -using System.Reflection; -using System.Runtime.InteropServices; -using Speckle.Newtonsoft.Json; -using Speckle.Sdk.Api.GraphQL.Models; -using Speckle.Sdk.Common; -using Speckle.Sdk.Credentials; -using Speckle.Sdk.Helpers; -using Speckle.Sdk.Host; using Speckle.Sdk.Logging; -using Speckle.Sdk.Models; -using Speckle.Sdk.Transports; namespace Speckle.Sdk.Api; public static class Helpers { public const string RELEASES_URL = "https://releases.speckle.dev"; - private const string FEEDS_ENDPOINT = RELEASES_URL + "/manager2/feeds"; - - /// - /// Helper method to Receive from a Speckle Server. - /// - /// Stream URL or Id to receive from. If the URL contains branchName, commitId or objectId those will be used, otherwise the latest commit from main will be received. - /// Account to use. If not provided the default account will be used. - /// Action invoked on progress iterations. - /// Action invoked once the total count of objects is known. - /// - public static async Task Receive( - this IServerTransportFactory serverTransportFactory, - string stream, - Account? account = null, - Action>? onProgressAction = null, - Action? onTotalChildrenCountKnown = null - ) - { - var sw = new StreamWrapper(stream); - - try - { - account ??= await sw.GetAccount().ConfigureAwait(false); - } - catch (SpeckleException) - { - if (string.IsNullOrEmpty(sw.StreamId)) - { - throw; - } - - //Fallback to a non authed account - account = new Account - { - token = "", - serverInfo = new ServerInfo { url = sw.ServerUrl }, - userInfo = new UserInfo() - }; - } - - using var client = new Client(account); - using var transport = serverTransportFactory.Create(client.Account, sw.StreamId); - - string objectId = ""; - Commit? commit = null; - - //OBJECT URL - if (!string.IsNullOrEmpty(sw.ObjectId)) - { - objectId = sw.ObjectId.NotNull(); - } - //COMMIT URL - else if (!string.IsNullOrEmpty(sw.CommitId)) - { - commit = await client.CommitGet(sw.StreamId, sw.CommitId.NotNull()).ConfigureAwait(false); - objectId = commit.referencedObject; - } - //BRANCH URL OR STREAM URL - else - { - var branchName = string.IsNullOrEmpty(sw.BranchName) ? "main" : sw.BranchName; - - var branch = await client.BranchGet(sw.StreamId, branchName.NotNull(), 1).ConfigureAwait(false); - if (branch.commits.items.Count == 0) - { - throw new SpeckleException("The selected branch has no commits."); - } - - commit = branch.commits.items[0]; - objectId = branch.commits.items[0].referencedObject; - } - - Analytics.TrackEvent( - client.Account, - Analytics.Events.Receive, - new Dictionary - { - { "sourceHostApp", HostApplications.GetHostAppFromString(commit.NotNull().sourceApplication).Slug }, - { "sourceHostAppVersion", commit.sourceApplication } - } - ); - - var receiveRes = await Operations - .Receive( - objectId, - transport, - onProgressAction: onProgressAction, - onTotalChildrenCountKnown: onTotalChildrenCountKnown - ) - .ConfigureAwait(false); - - try - { - await client - .CommitReceived( - new CommitReceivedInput - { - streamId = sw.StreamId, - commitId = commit?.id, - message = commit?.message, - sourceApplication = "Other" - } - ) - .ConfigureAwait(false); - } - catch (Exception ex) when (!ex.IsFatal()) - { - // Do nothing! - } - return receiveRes; - } /// /// value to fallback to if the given is diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs b/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs index 081ba3b2..cdb048e9 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.Receive.cs @@ -108,7 +108,7 @@ public static async Task Receive( using var activity = SpeckleActivityFactory.Start("Deserialize"); // Proceed to deserialize the object, now safely knowing that all its children are present in the local (fast) transport. - Base res = await serializer.Deserialize(objString); + Base res = await serializer.Deserialize(objString).ConfigureAwait(false); timer.Stop(); SpeckleLog.Logger.Information( diff --git a/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs b/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs index d2b602be..77b0b0a6 100644 --- a/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs +++ b/src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs @@ -1,5 +1,4 @@ using Speckle.Newtonsoft.Json; -using Speckle.Sdk.Logging; using Speckle.Sdk.Models; using Speckle.Sdk.Serialisation; using Speckle.Sdk.Transports; @@ -40,6 +39,6 @@ public static string Serialize(Base value, CancellationToken cancellationToken = public static async Task Deserialize(string value, CancellationToken cancellationToken = default) { var deserializer = new SpeckleObjectDeserializer { CancellationToken = cancellationToken }; - return await deserializer.Deserialize(value); + return await deserializer.Deserialize(value).ConfigureAwait(false); } } diff --git a/src/Speckle.Sdk/Common/Exceptions.cs b/src/Speckle.Sdk/Common/Exceptions.cs index b008e8c1..e2db5880 100644 --- a/src/Speckle.Sdk/Common/Exceptions.cs +++ b/src/Speckle.Sdk/Common/Exceptions.cs @@ -1,5 +1,3 @@ -using Speckle.Sdk.Logging; - namespace Speckle.Sdk.Common; /// diff --git a/src/Speckle.Sdk/Common/HashCode.cs b/src/Speckle.Sdk/Common/HashCode.cs index b1a43d24..273f58cb 100644 --- a/src/Speckle.Sdk/Common/HashCode.cs +++ b/src/Speckle.Sdk/Common/HashCode.cs @@ -7,21 +7,21 @@ namespace Speckle.Sdk.Common; /// public readonly struct HashCode : IEquatable { - private const int EmptyCollectionPrimeNumber = 19; - private readonly int value; + private const int EMPTY_COLLECTION_PRIME_NUMBER = 19; + private readonly int _value; /// /// Initializes a new instance of the struct. /// /// The value. - private HashCode(int value) => this.value = value; + private HashCode(int value) => _value = value; /// /// Performs an implicit conversion from to . /// /// The hash code. /// The result of the conversion. - public static implicit operator int(HashCode hashCode) => hashCode.value; + public static implicit operator int(HashCode hashCode) => hashCode.ToInt32(); /// /// Implements the operator ==. @@ -53,7 +53,7 @@ namespace Speckle.Sdk.Common; /// The type of the items. /// The collection. /// The new hash code. - public static HashCode OfEach(IEnumerable items) => + public static HashCode OfEach(IEnumerable? items) => items == null ? new HashCode(0) : new HashCode(GetHashCode(items, 0)); /// @@ -62,7 +62,7 @@ public static HashCode OfEach(IEnumerable items) => /// The type of the item. /// The item. /// The new hash code. - public HashCode And(T item) => new HashCode(CombineHashCodes(this.value, GetHashCode(item))); + public HashCode And(T item) => new HashCode(CombineHashCodes(this._value, GetHashCode(item))); /// /// Adds the hash code of the specified items in the collection. @@ -70,38 +70,32 @@ public static HashCode OfEach(IEnumerable items) => /// The type of the items. /// The collection. /// The new hash code. - public HashCode AndEach(IEnumerable items) + public HashCode AndEach(IEnumerable? items) { if (items == null) { - return new HashCode(this.value); + return new HashCode(this._value); } - return new HashCode(GetHashCode(items, this.value)); + return new HashCode(GetHashCode(items, this._value)); } /// - public bool Equals(HashCode other) => this.value.Equals(other.value); + public bool Equals(HashCode other) => this._value.Equals(other._value); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { - if (obj is HashCode) + if (obj is HashCode code) { - return this.Equals((HashCode)obj); + return this.Equals(code); } return false; } - /// - /// Throws . - /// - /// Does not return. - /// Implicitly convert this struct to an to get the hash code. [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => - throw new NotSupportedException("Implicitly convert this struct to an int to get the hash code."); + public override int GetHashCode() => ToInt32(); private static int CombineHashCodes(int h1, int h2) { @@ -130,9 +124,14 @@ private static int GetHashCode(IEnumerable items, int startHashCode) } else { - temp = CombineHashCodes(temp, EmptyCollectionPrimeNumber); + temp = CombineHashCodes(temp, EMPTY_COLLECTION_PRIME_NUMBER); } return temp; } + + public int ToInt32() + { + return _value; + } } diff --git a/src/Speckle.Sdk/Credentials/AccountManager.cs b/src/Speckle.Sdk/Credentials/AccountManager.cs index e817d913..c7853e30 100644 --- a/src/Speckle.Sdk/Credentials/AccountManager.cs +++ b/src/Speckle.Sdk/Credentials/AccountManager.cs @@ -206,9 +206,8 @@ internal static async Task GetUserServerInfo( /// /// The Default Server URL for authentication, can be overridden by placing a file with the alternatrive url in the Speckle folder or with an ENV_VAR /// - public static string GetDefaultServerUrl() + public static Uri GetDefaultServerUrl() { - var serverUrl = DEFAULT_SERVER_URL; var customServerUrl = ""; // first mechanism, check for local file @@ -227,14 +226,13 @@ public static string GetDefaultServerUrl() if (!string.IsNullOrEmpty(customServerUrl)) { - Uri.TryCreate(customServerUrl, UriKind.Absolute, out Uri url); - if (url != null) + if (Uri.TryCreate(customServerUrl, UriKind.Absolute, out Uri? url)) { - serverUrl = customServerUrl.TrimEnd('/'); + return url; } } - return serverUrl; + return new Uri(DEFAULT_SERVER_URL); } /// The Id of the account to fetch @@ -465,9 +463,9 @@ public static void RemoveAccount(string id) //TODO: reset default account s_accountStorage.DeleteObject(id); - var accounts = GetAccounts(); - //BUG: Clearly this is a bug bug bug! - if (accounts.Any() && !accounts.Any(x => x.isDefault)) + var accounts = GetAccounts().ToArray(); + + if (accounts.Length != 0 && !accounts.Any(x => x.isDefault)) { ChangeDefaultAccount(accounts.First().id); } @@ -529,10 +527,10 @@ public static void ChangeDefaultAccount(string id) return searchResult; } - private static string EnsureCorrectServerUrl(string server) + private static Uri EnsureCorrectServerUrl(Uri? server) { var localUrl = server; - if (string.IsNullOrEmpty(localUrl)) + if (localUrl == null) { localUrl = GetDefaultServerUrl(); SpeckleLog.Logger.Debug( @@ -540,7 +538,7 @@ private static string EnsureCorrectServerUrl(string server) localUrl ); } - return localUrl.TrimEnd('/'); + return localUrl; } private static void EnsureGetAccessCodeFlowIsSupported() @@ -552,7 +550,7 @@ private static void EnsureGetAccessCodeFlowIsSupported() } } - private static async Task GetAccessCode(string server, string challenge, TimeSpan timeout) + private static async Task GetAccessCode(Uri server, string challenge, TimeSpan timeout) { EnsureGetAccessCodeFlowIsSupported(); @@ -603,7 +601,7 @@ private static async Task GetAccessCode(string server, string challenge, "Local auth flow failed to complete within the timeout window. Access code is {accessCode}", accessCode ); - throw new Exception("Local auth flow failed to complete within the timeout window"); + throw new AuthFlowException("Local auth flow failed to complete within the timeout window"); } if (task.IsFaulted) @@ -611,9 +609,9 @@ private static async Task GetAccessCode(string server, string challenge, SpeckleLog.Logger.Error( task.Exception, "Getting access code flow failed with {exceptionMessage}", - task.Exception.Message + task.Exception?.Message ); - throw new Exception($"Auth flow failed: {task.Exception.Message}", task.Exception); + throw new AuthFlowException($"Auth flow failed: {task.Exception?.Message}", task.Exception); } // task completed within timeout @@ -624,12 +622,12 @@ private static async Task GetAccessCode(string server, string challenge, return accessCode; } - private static async Task CreateAccount(string accessCode, string challenge, string server) + private static async Task CreateAccount(string accessCode, string challenge, Uri server) { try { var tokenResponse = await GetToken(accessCode, challenge, server).ConfigureAwait(false); - var userResponse = await GetUserServerInfo(tokenResponse.token, new(server)).ConfigureAwait(false); + var userResponse = await GetUserServerInfo(tokenResponse.token, server).ConfigureAwait(false); var account = new Account { @@ -703,7 +701,7 @@ private static void UnlockAccountAddFlow() /// /// Server to use to add the account, if not provied the default Server will be used /// - public static async Task AddAccount(string server = "") + public static async Task AddAccount(Uri? server = null) { SpeckleLog.Logger.Debug("Starting to add account for {serverUrl}", server); @@ -747,7 +745,7 @@ public static async Task AddAccount(string server = "") } } - private static async Task GetToken(string accessCode, string challenge, string server) + private static async Task GetToken(string accessCode, string challenge, Uri server) { try { @@ -763,7 +761,7 @@ private static async Task GetToken(string accessCode, str using var content = new StringContent(JsonConvert.SerializeObject(body)); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); - var response = await client.PostAsync($"{server}/auth/token", content).ConfigureAwait(false); + var response = await client.PostAsync(new Uri(server, "/auth/token"), content).ConfigureAwait(false); return JsonConvert .DeserializeObject(await response.Content.ReadAsStringAsync().ConfigureAwait(false)) @@ -817,7 +815,7 @@ private static async Task IsFrontend2Server(Uri server) var headers = response.Headers; const string HEADER = "x-speckle-frontend-2"; - if (!headers.TryGetValues(HEADER, out IEnumerable values)) + if (!headers.TryGetValues(HEADER, out IEnumerable? values)) { return false; } diff --git a/src/Speckle.Sdk/Credentials/AuthFlowException.cs b/src/Speckle.Sdk/Credentials/AuthFlowException.cs new file mode 100644 index 00000000..65d32a2e --- /dev/null +++ b/src/Speckle.Sdk/Credentials/AuthFlowException.cs @@ -0,0 +1,12 @@ +namespace Speckle.Sdk.Credentials; + +public sealed class AuthFlowException : Exception +{ + public AuthFlowException(string? message, Exception? innerException) + : base(message, innerException) { } + + public AuthFlowException(string? message) + : base(message) { } + + public AuthFlowException() { } +} diff --git a/src/Speckle.Sdk/Credentials/Exceptions.cs b/src/Speckle.Sdk/Credentials/Exceptions.cs index fbf29439..e33738a0 100644 --- a/src/Speckle.Sdk/Credentials/Exceptions.cs +++ b/src/Speckle.Sdk/Credentials/Exceptions.cs @@ -1,5 +1,3 @@ -using Speckle.Sdk.Logging; - namespace Speckle.Sdk.Credentials; public class SpeckleAccountManagerException : SpeckleException diff --git a/src/Speckle.Sdk/Credentials/Responses.cs b/src/Speckle.Sdk/Credentials/Responses.cs index 65574da0..17ca4895 100644 --- a/src/Speckle.Sdk/Credentials/Responses.cs +++ b/src/Speckle.Sdk/Credentials/Responses.cs @@ -1,5 +1,4 @@ using System.Runtime.InteropServices; -using Speckle.Sdk.Api; using Speckle.Sdk.Api.GraphQL.Models; namespace Speckle.Sdk.Credentials; @@ -25,26 +24,4 @@ public sealed class UserInfo public string email { get; init; } public string? company { get; init; } public string? avatar { get; init; } - - [Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] - public Streams streams { get; init; } - - [Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] - public Commits commits { get; init; } -} - -[ClassInterface(ClassInterfaceType.AutoDual)] -[ComVisible(true)] -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Streams -{ - public int totalCount { get; set; } -} - -[ClassInterface(ClassInterfaceType.AutoDual)] -[ComVisible(true)] -[Obsolete(DeprecationMessages.FE1_DEPRECATION_MESSAGE)] -public class Commits -{ - public int totalCount { get; set; } } diff --git a/src/Speckle.Sdk/Credentials/StreamWrapper.cs b/src/Speckle.Sdk/Credentials/StreamWrapper.cs index 95248c82..957f94b0 100644 --- a/src/Speckle.Sdk/Credentials/StreamWrapper.cs +++ b/src/Speckle.Sdk/Credentials/StreamWrapper.cs @@ -1,13 +1,14 @@ +using System.Diagnostics.CodeAnalysis; using System.Text.RegularExpressions; using System.Web; using Speckle.Sdk.Api; -using Speckle.Sdk.Api.GraphQL; using Speckle.Sdk.Common; using Speckle.Sdk.Helpers; -using Speckle.Sdk.Logging; namespace Speckle.Sdk.Credentials; +[SuppressMessage("Design", "CA1054:URI-like parameters should not be strings", Justification = "Class needs re-write")] +[SuppressMessage("Usage", "CA2234:Pass system uri objects instead of strings", Justification = "Class needs re-write")] public class StreamWrapper { private Account? _account; @@ -212,7 +213,7 @@ private void StreamWrapperFromUrl(string streamUrl) switch (uri.Segments.Length) { case 3: // ie http://speckle.server/streams/8fecc9aa6d - if (uri.Segments[1].ToLowerInvariant() != "streams/") + if (!uri.Segments[1].Equals("streams/", StringComparison.InvariantCultureIgnoreCase)) { throw new SpeckleException($"Cannot parse {uri} into a stream wrapper class."); } @@ -223,7 +224,7 @@ private void StreamWrapperFromUrl(string streamUrl) break; case 4: // ie https://speckle.server/streams/0c6ad366c4/globals/ - if (uri.Segments[3].ToLowerInvariant().StartsWith("globals")) + if (uri.Segments[3].StartsWith("globals", StringComparison.InvariantCultureIgnoreCase)) { StreamId = uri.Segments[2].Replace("/", ""); BranchName = Uri.UnescapeDataString(uri.Segments[3].Replace("/", "")); diff --git a/src/Speckle.Sdk/Helpers/Http.cs b/src/Speckle.Sdk/Helpers/Http.cs index b1b38811..fecbac47 100644 --- a/src/Speckle.Sdk/Helpers/Http.cs +++ b/src/Speckle.Sdk/Helpers/Http.cs @@ -49,7 +49,7 @@ public static IAsyncPolicy HttpAsyncPolicy( /// True if the user is connected to the internet, false otherwise. public static async Task UserHasInternet() { - string? defaultServer = null; + Uri? defaultServer = null; try { //Perform a quick ping test e.g. to cloudflaire dns, as is quicker than pinging server @@ -59,8 +59,7 @@ public static async Task UserHasInternet() } defaultServer = AccountManager.GetDefaultServerUrl(); - Uri serverUrl = new(defaultServer); - await HttpPing(serverUrl).ConfigureAwait(false); + await HttpPing(defaultServer).ConfigureAwait(false); return true; } catch (HttpRequestException ex) @@ -169,7 +168,9 @@ public static bool CanAddAuth(string? authToken, out string? bearerHeader) { if (!string.IsNullOrEmpty(authToken)) { - bearerHeader = authToken.NotNull().ToLowerInvariant().Contains("bearer") ? authToken : $"Bearer {authToken}"; + bearerHeader = authToken.NotNull().StartsWith("bearer", StringComparison.InvariantCultureIgnoreCase) + ? authToken + : $"Bearer {authToken}"; return true; } diff --git a/src/Speckle.Sdk/Helpers/SpeckleHttpClientHandler.cs b/src/Speckle.Sdk/Helpers/SpeckleHttpClientHandler.cs index 9669c091..1bda813c 100644 --- a/src/Speckle.Sdk/Helpers/SpeckleHttpClientHandler.cs +++ b/src/Speckle.Sdk/Helpers/SpeckleHttpClientHandler.cs @@ -54,10 +54,8 @@ CancellationToken cancellationToken activity?.SetTag("retryCount", retryCount); SpeckleLog.Logger.Information( - "Execution of http request to {httpScheme}://{hostUrl}{relativeUrl} {resultStatus} with {httpStatusCode} after {elapsed} seconds and {retryCount} retries. Request correlation ID: {correlationId}", - request.RequestUri.Scheme, - request.RequestUri.Host, - request.RequestUri.PathAndQuery, + "Execution of http request to {url} {resultStatus} with {httpStatusCode} after {elapsed} seconds and {retryCount} retries. Request correlation ID: {correlationId}", + request.RequestUri, policyResult.Outcome == OutcomeType.Successful ? "succeeded" : "failed", policyResult.Result?.StatusCode, sw.Elapsed.TotalSeconds, diff --git a/src/Speckle.Sdk/Helpers/State.cs b/src/Speckle.Sdk/Helpers/State.cs deleted file mode 100644 index 657b7225..00000000 --- a/src/Speckle.Sdk/Helpers/State.cs +++ /dev/null @@ -1,87 +0,0 @@ -#nullable disable -namespace Speckle.Sdk.Helpers; - -public class State : IDisposable - where T : State, new() -{ - private static T root; - private static T current; - private T previous = current; - - private static readonly object StateChangeLock = new(); - - protected State() - { - lock (StateChangeLock) - { - current = (T)this; - if (root == null) - { - root = (T)this; - } - } - } - - void IDisposable.Dispose() - { - lock (StateChangeLock) - { - if (previous == null) - { - return; // Already disposed or root - } - - if (current == this) - { - current = previous; - } - else - { - // If this state is still in the stack is safe to pop it - var state = this; - do - { - if (state == root) - { - current = previous; - break; - } - - state = state.previous; - } while (state != null); - } - - previous = null; - } - } - - public static T Peek => current; - - public static T Push() - { - lock (StateChangeLock) - { - var peek = current ?? new T(); - var top = (T)peek.MemberwiseClone(); - top.previous = current; - - return current = top; - } - } - - public static void Pop() - { - lock (StateChangeLock) - { - ((IDisposable)current).Dispose(); - } - } - - protected void Pull() - { - lock (StateChangeLock) - { - ((IDisposable)this).Dispose(); - } - } -} diff --git a/src/Speckle.Sdk/Host/Attributes.cs b/src/Speckle.Sdk/Host/Attributes.cs index 26273628..c5e94a77 100644 --- a/src/Speckle.Sdk/Host/Attributes.cs +++ b/src/Speckle.Sdk/Host/Attributes.cs @@ -2,12 +2,12 @@ namespace Speckle.Sdk.Host; [AttributeUsage(AttributeTargets.Constructor)] -public sealed class SchemaInfo : Attribute +public sealed class SchemaInfoAttribute : Attribute { - public SchemaInfo(string name, string description) + public SchemaInfoAttribute(string name, string description) : this(name, description, null, null) { } - public SchemaInfo(string name, string description, string category, string subcategory) + public SchemaInfoAttribute(string name, string description, string category, string subcategory) { Name = name; Description = description; @@ -25,12 +25,12 @@ public SchemaInfo(string name, string description, string category, string subca } [AttributeUsage(AttributeTargets.Constructor)] -public sealed class SchemaDeprecated : Attribute { } +public sealed class SchemaDeprecatedAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter)] -public sealed class SchemaParamInfo : Attribute +public sealed class SchemaParamInfoAttribute : Attribute { - public SchemaParamInfo(string description) + public SchemaParamInfoAttribute(string description) { Description = description; } @@ -42,7 +42,7 @@ public SchemaParamInfo(string description) /// Used to indicate which is the main input parameter of the schema builder component. Schema info will be attached to this object. /// [AttributeUsage(AttributeTargets.Parameter)] -public sealed class SchemaMainParam : Attribute { } +public sealed class SchemaMainParamAttribute : Attribute { } // TODO: this could be nuked, as it's only used to hide props on Base, // which we might want to expose anyways... @@ -50,7 +50,7 @@ public sealed class SchemaMainParam : Attribute { } /// Used to ignore properties from expand objects etc /// [AttributeUsage(AttributeTargets.Property)] -public sealed class SchemaIgnore : Attribute { } +public sealed class SchemaIgnoreAttribute : Attribute { } [AttributeUsage(AttributeTargets.Method)] public sealed class SchemaComputedAttribute : Attribute diff --git a/src/Speckle.Sdk/Host/TypeLoader.cs b/src/Speckle.Sdk/Host/TypeLoader.cs index 1464a977..600fa24a 100644 --- a/src/Speckle.Sdk/Host/TypeLoader.cs +++ b/src/Speckle.Sdk/Host/TypeLoader.cs @@ -14,7 +14,7 @@ public static class TypeLoader private static ConcurrentDictionary s_cachedTypes = new(); private static ConcurrentDictionary s_fullTypeStrings = new(); - private static ConcurrentDictionary s_jsonPropertyAttribute = new(); + private static ConcurrentDictionary s_jsonPropertyAttribute = new(); private static ConcurrentDictionary> s_propInfoCache = new(); public static IEnumerable Types => s_availableTypes; @@ -171,6 +171,10 @@ public static LoadedType ParseType(Type type) throw new InvalidOperationException($"{type.FullName} inherits from Base has no SpeckleTypeAttribute"); } var deprecatedSpeckleTypes = type.GetCustomAttributes(); - return new LoadedType(speckleType.Name, type, deprecatedSpeckleTypes.Select(x => x.Name).ToList()); + return new LoadedType( + speckleType.SpeckleTypeName, + type, + deprecatedSpeckleTypes.Select(x => x.SpeckleTypeName).ToList() + ); } } diff --git a/src/Speckle.Sdk/Logging/Analytics.cs b/src/Speckle.Sdk/Logging/Analytics.cs index 7e35564c..a8ead990 100644 --- a/src/Speckle.Sdk/Logging/Analytics.cs +++ b/src/Speckle.Sdk/Logging/Analytics.cs @@ -75,7 +75,7 @@ public enum Events } private const string MIXPANEL_TOKEN = "acd87c5a50b56df91a795e999812a3a4"; - private const string MIXPANEL_SERVER = "https://analytics.speckle.systems"; + private static readonly Uri s_mixpanelServer = new("https://analytics.speckle.systems"); /// /// Cached email @@ -240,7 +240,7 @@ private static void TrackEvent( using HttpClient client = new(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); query.Headers.ContentType = new MediaTypeHeaderValue("application/json"); - var res = await client.PostAsync(MIXPANEL_SERVER + "/track?ip=1", query).ConfigureAwait(false); + var res = await client.PostAsync(new Uri(s_mixpanelServer, "/track?ip=1"), query).ConfigureAwait(false); res.EnsureSuccessStatusCode(); } catch (Exception ex) when (!ex.IsFatal()) @@ -277,7 +277,9 @@ internal static void AddConnectorToProfile(string hashedEmail, string connector) using HttpClient client = Http.GetHttpProxyClient(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); query.Headers.ContentType = new MediaTypeHeaderValue("application/json"); - var res = await client.PostAsync(MIXPANEL_SERVER + "/engage#profile-union", query).ConfigureAwait(false); + var res = await client + .PostAsync(new Uri(s_mixpanelServer, "/engage#profile-union"), query) + .ConfigureAwait(false); res.EnsureSuccessStatusCode(); } catch (Exception ex) when (!ex.IsFatal()) @@ -288,7 +290,7 @@ internal static void AddConnectorToProfile(string hashedEmail, string connector) }); } - internal static void IdentifyProfile(string hashedEmail, string connector) + internal static void IdentifyProfile(string hashedEmail) { Task.Run(async () => { @@ -309,7 +311,7 @@ internal static void IdentifyProfile(string hashedEmail, string connector) using HttpClient client = Http.GetHttpProxyClient(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); query.Headers.ContentType = new MediaTypeHeaderValue("application/json"); - var res = await client.PostAsync(MIXPANEL_SERVER + "/engage#profile-set", query).ConfigureAwait(false); + var res = await client.PostAsync(new Uri(s_mixpanelServer, "/engage#profile-set"), query).ConfigureAwait(false); res.EnsureSuccessStatusCode(); } catch (Exception ex) when (!ex.IsFatal()) diff --git a/src/Speckle.Sdk/Models/ApplicationObject.cs b/src/Speckle.Sdk/Models/ApplicationObject.cs deleted file mode 100644 index e8b4827c..00000000 --- a/src/Speckle.Sdk/Models/ApplicationObject.cs +++ /dev/null @@ -1,138 +0,0 @@ -#nullable disable -using Speckle.Newtonsoft.Json; - -namespace Speckle.Sdk.Models; - -/// -/// A simple wrapper to keep track of the relationship between speckle objects and their host-application siblings in cases where the -/// cannot correspond with the (ie, on receiving operations). -/// -public class ApplicationObject -{ - public enum State - { - Unknown = default, - Created, // Speckle object created on send, or native objects created on receive - Skipped, // Speckle or Application object is not going to be sent or received - Updated, // Application object is replacing an existing object in the application - Failed, // Tried to convert & send or convert & bake but something went wrong - Removed, //Removed object from application - } - - public ApplicationObject(string id, string type) - { - OriginalId = id; - Descriptor = type; - Status = State.Unknown; - } - - /// - /// ID of the object from host application that generated it. - /// - public string applicationId { get; set; } - - /// - /// The container for the object in the native application - /// - public string Container { get; set; } - - /// - /// Indicates if conversion is supported by the converter - /// - public bool Convertible { get; set; } - - /// - /// The fallback values if direct conversion is not available, typically displayValue - /// - [JsonIgnore] - public List Fallback { get; set; } = new(); - - /// - /// The Speckle id (on receive) or native id (on send) - /// - /// - /// Used to retrieve this object in ProgressReport.GetReportObject(), typically to pass between connectors and converters - /// - public string OriginalId { get; set; } - - /// - /// A descriptive string to describe the object. Use the object type as default. - /// - public string Descriptor { get; set; } - - /// - /// The created object ids associated with this object - /// - /// - /// On send, this is currently left empty as generating Speckle ids would be performance expensive - /// - public List CreatedIds { get; set; } = new(); - - /// - /// Conversion status of object - /// - public State Status { get; set; } - - /// - /// Conversion notes or other important information to expose to the user - /// - public List Log { get; set; } = new(); - - /// - /// Converted objects corresponding to this object - /// - /// - /// Used during receive for convenience, corresponds to CreatedIds - /// - [JsonIgnore] - public List Converted { get; set; } = new(); - - public void Update( - string createdId = null, - List createdIds = null, - State? status = null, - string container = null, - List log = null, - string logItem = null, - List converted = null, - object convertedItem = null, - string descriptor = null - ) - { - createdIds?.Where(o => !string.IsNullOrEmpty(o) && !CreatedIds.Contains(o))?.ToList().ForEach(CreatedIds.Add); - - if (createdId != null && !CreatedIds.Contains(createdId)) - { - CreatedIds.Add(createdId); - } - - if (status.HasValue) - { - Status = status.Value; - } - - log?.Where(o => !string.IsNullOrEmpty(o) && !Log.Contains(o))?.ToList().ForEach(Log.Add); - - if (!string.IsNullOrEmpty(logItem) && !Log.Contains(logItem)) - { - Log.Add(logItem); - } - - if (convertedItem != null && !Converted.Contains(convertedItem)) - { - Converted.Add(convertedItem); - } - - converted?.Where(o => o != null && !Converted.Contains(o))?.ToList().ForEach(Converted.Add); - - if (!string.IsNullOrEmpty(container)) - { - Container = container; - } - - if (!string.IsNullOrEmpty(descriptor)) - { - Descriptor = descriptor; - } - } -} diff --git a/src/Speckle.Sdk/Models/Attributes.cs b/src/Speckle.Sdk/Models/Attributes.cs index a8720216..808c24b8 100644 --- a/src/Speckle.Sdk/Models/Attributes.cs +++ b/src/Speckle.Sdk/Models/Attributes.cs @@ -6,7 +6,7 @@ namespace Speckle.Sdk.Models; /// Only applies to properties of types derived from the Base class. /// [AttributeUsage(AttributeTargets.Property)] -public sealed class DetachProperty : Attribute +public sealed class DetachPropertyAttribute : Attribute { /// /// Flags an object's property as being detachable. @@ -14,7 +14,7 @@ public sealed class DetachProperty : Attribute /// Only applies to properties of types derived from the Base class. /// /// Whether to detach the property or not. - public DetachProperty(bool detachable = true) + public DetachPropertyAttribute(bool detachable = true) { Detachable = detachable; } @@ -23,14 +23,14 @@ public DetachProperty(bool detachable = true) } /// -/// Flags a list or array as splittable into chunks during serialisation. These chunks will be recomposed on deserialisation into the original list. Note: this attribute should be used in conjunction with . +/// Flags a list or array as splittable into chunks during serialisation. These chunks will be recomposed on deserialisation into the original list. Note: this attribute should be used in conjunction with . /// Use this attribute on properties that can become very long and are not worth detaching into individual elements. /// Objects per chunk: for simple types, like numbers, use a high value (>10000); for other objects, use a more conservative number depending on their serialised size. /// [AttributeUsage(AttributeTargets.Property)] -public sealed class Chunkable : Attribute +public sealed class ChunkableAttribute : Attribute { - public Chunkable(int maxObjCountPerChunk = 1000) + public ChunkableAttribute(int maxObjCountPerChunk = 1000) { MaxObjCountPerChunk = maxObjCountPerChunk; } diff --git a/src/Speckle.Sdk/Models/Base.cs b/src/Speckle.Sdk/Models/Base.cs index 7d84a024..3fb2d5ba 100644 --- a/src/Speckle.Sdk/Models/Base.cs +++ b/src/Speckle.Sdk/Models/Base.cs @@ -110,13 +110,13 @@ private static long CountDescendants(Base @base, ISet parsed) continue; } - var detachAttribute = prop.GetCustomAttribute(true); + var detachAttribute = prop.GetCustomAttribute(true); - object value = prop.GetValue(@base); + object? value = prop.GetValue(@base); if (detachAttribute is { Detachable: true }) { - var chunkAttribute = prop.GetCustomAttribute(true); + var chunkAttribute = prop.GetCustomAttribute(true); if (chunkAttribute == null) { count += HandleObjectCount(value, parsed); @@ -132,7 +132,7 @@ private static long CountDescendants(Base @base, ISet parsed) } } - var dynamicProps = @base.GetDynamicPropertyKeys(); + var dynamicProps = @base.DynamicPropertyKeys; foreach (var propName in dynamicProps) { if (!propName.StartsWith("@")) @@ -144,7 +144,7 @@ private static long CountDescendants(Base @base, ISet parsed) if (s_chunkSyntax.IsMatch(propName)) { var match = s_chunkSyntax.Match(propName); - _ = int.TryParse(match.Groups[match.Groups.Count - 1].Value, out int chunkSize); + _ = int.TryParse(match.Groups[^1].Value, out int chunkSize); if (chunkSize != -1 && @base[propName] is IList asList) { diff --git a/src/Speckle.Sdk/Models/Blob.cs b/src/Speckle.Sdk/Models/Blob.cs index b9626e63..ad6706b8 100644 --- a/src/Speckle.Sdk/Models/Blob.cs +++ b/src/Speckle.Sdk/Models/Blob.cs @@ -1,5 +1,4 @@ #nullable disable -using System.Diagnostics.CodeAnalysis; using System.Runtime.Serialization; using Speckle.Newtonsoft.Json; @@ -64,6 +63,6 @@ internal void OnDeserialized(StreamingContext context) public string GetLocalDestinationPath(string blobStorageFolder) { var fileName = Path.GetFileName(filePath); - return Path.Combine(blobStorageFolder, $"{id.Substring(0, 10)}-{fileName}"); + return Path.Combine(blobStorageFolder, $"{id[..10]}-{fileName}"); } } diff --git a/src/Speckle.Sdk/Models/DeprecatedSpeckleTypeAttribute.cs b/src/Speckle.Sdk/Models/DeprecatedSpeckleTypeAttribute.cs index 46087c3f..cbdf97a3 100644 --- a/src/Speckle.Sdk/Models/DeprecatedSpeckleTypeAttribute.cs +++ b/src/Speckle.Sdk/Models/DeprecatedSpeckleTypeAttribute.cs @@ -1,8 +1,7 @@ -#nullable disable namespace Speckle.Sdk.Models; [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] -public class DeprecatedSpeckleTypeAttribute(string speckleTypeName) : Attribute +public sealed class DeprecatedSpeckleTypeAttribute(string speckleTypeName) : Attribute { - public string Name => speckleTypeName; + public string SpeckleTypeName => speckleTypeName; } diff --git a/src/Speckle.Sdk/Models/DynamicBase.cs b/src/Speckle.Sdk/Models/DynamicBase.cs index c069aa9b..fcf8e3a1 100644 --- a/src/Speckle.Sdk/Models/DynamicBase.cs +++ b/src/Speckle.Sdk/Models/DynamicBase.cs @@ -1,5 +1,6 @@ using System.Dynamic; using System.Reflection; +using Speckle.Newtonsoft.Json; using Speckle.Sdk.Host; using Speckle.Sdk.Logging; @@ -223,7 +224,7 @@ public static IEnumerable GetInstanceMembers(Type t) .GetBaseProperties(GetType()) .Where(x => { - var hasIgnored = x.IsDefined(typeof(SchemaIgnore), true); + var hasIgnored = x.IsDefined(typeof(SchemaIgnoreAttribute), true); var hasObsolete = x.IsDefined(typeof(ObsoleteAttribute), true); // If obsolete is false and prop has obsolete attr @@ -271,10 +272,8 @@ public static IEnumerable GetInstanceMembers(Type t) /// Gets the dynamically added property names only. /// /// - public IReadOnlyCollection GetDynamicPropertyKeys() - { - return _properties.Keys; - } + [JsonIgnore] + public IReadOnlyCollection DynamicPropertyKeys => _properties.Keys; } /// diff --git a/src/Speckle.Sdk/Models/DynamicBaseMemberType.cs b/src/Speckle.Sdk/Models/DynamicBaseMemberType.cs index ba9d60b2..7a336bee 100644 --- a/src/Speckle.Sdk/Models/DynamicBaseMemberType.cs +++ b/src/Speckle.Sdk/Models/DynamicBaseMemberType.cs @@ -24,7 +24,7 @@ public enum DynamicBaseMemberType Obsolete = 4, /// - /// The typed members flagged with attribute. + /// The typed members flagged with attribute. /// SchemaIgnored = 8, @@ -34,12 +34,12 @@ public enum DynamicBaseMemberType SchemaComputed = 16, /// - /// All the typed members, including ones with or attributes. + /// All the typed members, including ones with or attributes. /// InstanceAll = Instance + Obsolete + SchemaIgnored, /// - /// All the members, including dynamic and instance members flagged with or attributes + /// All the members, including dynamic and instance members flagged with or attributes /// All = InstanceAll + Dynamic } diff --git a/src/Speckle.Sdk/Models/Extras.cs b/src/Speckle.Sdk/Models/Extras.cs index 6d5844ba..d87f1e4b 100644 --- a/src/Speckle.Sdk/Models/Extras.cs +++ b/src/Speckle.Sdk/Models/Extras.cs @@ -1,5 +1,3 @@ -#nullable disable - namespace Speckle.Sdk.Models; /// @@ -9,15 +7,14 @@ namespace Speckle.Sdk.Models; [SpeckleType("Speckle.Core.Models.DataChunk")] public sealed class DataChunk : Base { - public List data { get; set; } = new(); + public required List data { get; init; } } -[SpeckleType("Speckle.Core.Models.ObjectReference")] +[DeprecatedSpeckleType("Speckle.Core.Models.ObjectReference")] +[SpeckleType("reference")] public sealed class ObjectReference : Base { - public new string speckle_type = "reference"; - - public string referencedId { get; set; } + public required string referencedId { get; init; } public Dictionary closure { get; set; } } diff --git a/src/Speckle.Sdk/Models/GraphTraversal/GraphTraversal.cs b/src/Speckle.Sdk/Models/GraphTraversal/GraphTraversal.cs index 16962b31..a9fbd637 100644 --- a/src/Speckle.Sdk/Models/GraphTraversal/GraphTraversal.cs +++ b/src/Speckle.Sdk/Models/GraphTraversal/GraphTraversal.cs @@ -13,6 +13,44 @@ protected override TraversalContext NewContext(Base current, string? propName, T { return new TraversalContext(current, propName, parent); } + + /// + /// Traverses supported Collections yielding objects. + /// Does not traverse , only (potentially nested) collections. + /// + /// The value to traverse + public static IEnumerable TraverseMember(object? value) + { + //TODO we should benchmark this, as yield returning like this could be suboptimal + switch (value) + { + case Base o: + yield return o; + break; + case IList list: + { + foreach (object? obj in list) + { + foreach (Base o in TraverseMember(obj)) + { + yield return o; + } + } + break; + } + case IDictionary dictionary: + { + foreach (object? obj in dictionary.Values) + { + foreach (Base o in TraverseMember(obj)) + { + yield return o; + } + } + break; + } + } + } } public abstract class GraphTraversal @@ -92,44 +130,6 @@ private void TraverseMemberToStack( protected abstract T NewContext(Base current, string? propName, T? parent); - /// - /// Traverses supported Collections yielding objects. - /// Does not traverse , only (potentially nested) collections. - /// - /// The value to traverse - public static IEnumerable TraverseMember(object? value) - { - //TODO we should benchmark this, as yield returning like this could be suboptimal - switch (value) - { - case Base o: - yield return o; - break; - case IList list: - { - foreach (object? obj in list) - { - foreach (Base o in TraverseMember(obj)) - { - yield return o; - } - } - break; - } - case IDictionary dictionary: - { - foreach (object? obj in dictionary.Values) - { - foreach (Base o in TraverseMember(obj)) - { - yield return o; - } - } - break; - } - } - } - private ITraversalRule GetActiveRuleOrDefault(Base o) { return GetActiveRule(o) ?? DefaultRule.Instance; diff --git a/src/Speckle.Sdk/Models/InvalidPropNameException.cs b/src/Speckle.Sdk/Models/InvalidPropNameException.cs index 486dbab0..f814c2a6 100644 --- a/src/Speckle.Sdk/Models/InvalidPropNameException.cs +++ b/src/Speckle.Sdk/Models/InvalidPropNameException.cs @@ -1,5 +1,3 @@ -using Speckle.Sdk.Logging; - namespace Speckle.Sdk.Models; public class InvalidPropNameException : SpeckleException diff --git a/src/Speckle.Sdk/Models/SpeckleTypeAttribute.cs b/src/Speckle.Sdk/Models/SpeckleTypeAttribute.cs index d9439471..af5c14a2 100644 --- a/src/Speckle.Sdk/Models/SpeckleTypeAttribute.cs +++ b/src/Speckle.Sdk/Models/SpeckleTypeAttribute.cs @@ -1,8 +1,7 @@ -#nullable disable namespace Speckle.Sdk.Models; [AttributeUsage(AttributeTargets.Class, Inherited = false)] -public class SpeckleTypeAttribute(string speckleTypeName) : Attribute +public sealed class SpeckleTypeAttribute(string speckleTypeName) : Attribute { - public string Name => speckleTypeName; + public string SpeckleTypeName => speckleTypeName; } diff --git a/src/Speckle.Sdk/Serialisation/BaseObjectDeserializerV2.cs b/src/Speckle.Sdk/Serialisation/BaseObjectDeserializerV2.cs new file mode 100644 index 00000000..e69de29b diff --git a/src/Speckle.Sdk/Serialisation/SpeckleDeserializeException.cs b/src/Speckle.Sdk/Serialisation/SpeckleDeserializeException.cs index 4ab2cec3..e19ea5aa 100644 --- a/src/Speckle.Sdk/Serialisation/SpeckleDeserializeException.cs +++ b/src/Speckle.Sdk/Serialisation/SpeckleDeserializeException.cs @@ -2,9 +2,11 @@ public class SpeckleDeserializeException : SpeckleException { - public SpeckleDeserializeException(string message, Exception? inner = null) + public SpeckleDeserializeException(string? message, Exception? inner = null) : base(message, inner) { } - public SpeckleDeserializeException(string message) + public SpeckleDeserializeException(string? message) : base(message) { } + + public SpeckleDeserializeException() { } } diff --git a/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs b/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs index a0ebc9f0..958609bc 100644 --- a/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs +++ b/src/Speckle.Sdk/Serialisation/SpeckleObjectDeserializer.cs @@ -34,7 +34,7 @@ public sealed class SpeckleObjectDeserializer public Action? OnProgressAction { get; set; } private long _currentCount; - private HashSet _ids = new(); + private readonly HashSet _ids = new(); private long _processedCount; public string? BlobStorageFolder { get; set; } diff --git a/src/Speckle.Sdk/Serialisation/SpeckleObjectSerializer.cs b/src/Speckle.Sdk/Serialisation/SpeckleObjectSerializer.cs index 653a09d7..19fab95f 100644 --- a/src/Speckle.Sdk/Serialisation/SpeckleObjectSerializer.cs +++ b/src/Speckle.Sdk/Serialisation/SpeckleObjectSerializer.cs @@ -107,7 +107,7 @@ public string Serialize(Base baseObj) // `Preserialize` means transforming all objects into the final form that will appear in json, with basic .net objects // (primitives, lists and dictionaries with string keys) - public object? SerializeProperty( + internal object? SerializeProperty( object? obj, JsonWriter writer, bool computeClosures = false, @@ -318,7 +318,7 @@ public string Serialize(Base baseObj) private Dictionary ExtractAllProperties(Base baseObj) { IReadOnlyList<(PropertyInfo, PropertyAttributeInfo)> typedProperties = GetTypedPropertiesWithCache(baseObj); - IReadOnlyCollection dynamicProperties = baseObj.GetDynamicPropertyKeys(); + IReadOnlyCollection dynamicProperties = baseObj.DynamicPropertyKeys; // propertyName -> (originalValue, isDetachable, isChunkable, chunkSize) Dictionary allProperties = @@ -406,7 +406,7 @@ private string SerializeBaseObject(Base baseObj, JsonWriter writer, IReadOnlyDic if (baseValue is IEnumerable chunkableCollection && detachInfo.IsChunkable) { List chunks = new(); - DataChunk crtChunk = new() { data = new List(detachInfo.ChunkSize) }; + DataChunk crtChunk = new() { data = new List(detachInfo.ChunkSize) }; foreach (object element in chunkableCollection) { @@ -414,7 +414,7 @@ private string SerializeBaseObject(Base baseObj, JsonWriter writer, IReadOnlyDic if (crtChunk.data.Count >= detachInfo.ChunkSize) { chunks.Add(crtChunk); - crtChunk = new DataChunk { data = new List(detachInfo.ChunkSize) }; + crtChunk = new DataChunk { data = new List(detachInfo.ChunkSize) }; } } @@ -518,8 +518,12 @@ private void StoreBlob(Blob obj) _ = typedProperty.GetValue(baseObj); - List detachableAttributes = typedProperty.GetCustomAttributes(true).ToList(); - List chunkableAttributes = typedProperty.GetCustomAttributes(true).ToList(); + List detachableAttributes = typedProperty + .GetCustomAttributes(true) + .ToList(); + List chunkableAttributes = typedProperty + .GetCustomAttributes(true) + .ToList(); bool isDetachable = detachableAttributes.Count > 0 && detachableAttributes[0].Detachable; bool isChunkable = chunkableAttributes.Count > 0; int chunkSize = isChunkable ? chunkableAttributes[0].MaxObjCountPerChunk : 1000; @@ -531,7 +535,7 @@ private void StoreBlob(Blob obj) return ret; } - public readonly struct PropertyAttributeInfo + internal readonly struct PropertyAttributeInfo { public PropertyAttributeInfo( bool isDetachable, diff --git a/src/Speckle.Sdk/Serialisation/SpeckleSerializerException.cs b/src/Speckle.Sdk/Serialisation/SpeckleSerializerException.cs index 68704da2..282f5b74 100644 --- a/src/Speckle.Sdk/Serialisation/SpeckleSerializerException.cs +++ b/src/Speckle.Sdk/Serialisation/SpeckleSerializerException.cs @@ -2,9 +2,11 @@ public class SpeckleSerializeException : SpeckleException { - public SpeckleSerializeException(string message, Exception? inner = null) + public SpeckleSerializeException(string? message, Exception? inner = null) : base(message, inner) { } - public SpeckleSerializeException(string message) + public SpeckleSerializeException(string? message) : base(message) { } + + public SpeckleSerializeException() { } } diff --git a/src/Speckle.Sdk/Serialisation/Utilities/ClosureParser.cs b/src/Speckle.Sdk/Serialisation/Utilities/ClosureParser.cs index 5ce07e3c..7f5dd483 100644 --- a/src/Speckle.Sdk/Serialisation/Utilities/ClosureParser.cs +++ b/src/Speckle.Sdk/Serialisation/Utilities/ClosureParser.cs @@ -1,4 +1,4 @@ -using Speckle.Newtonsoft.Json; +using Speckle.Newtonsoft.Json; using Speckle.Sdk.Common; namespace Speckle.Sdk.Serialisation.Utilities; diff --git a/src/Speckle.Sdk/Serialisation/Utilities/ValueConverter.cs b/src/Speckle.Sdk/Serialisation/Utilities/ValueConverter.cs index 53692ddf..78de5501 100644 --- a/src/Speckle.Sdk/Serialisation/Utilities/ValueConverter.cs +++ b/src/Speckle.Sdk/Serialisation/Utilities/ValueConverter.cs @@ -1,5 +1,5 @@ -using System.Buffers; using System.Collections; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Drawing; using System.Globalization; @@ -10,8 +10,13 @@ namespace Speckle.Sdk.Serialisation.Utilities; internal static class ValueConverter { - private static object[] _singleValue = new object[1]; + private static readonly object[] s_singleValue = new object[1]; + [SuppressMessage( + "Maintainability", + "CA1502:Avoid excessive complexity", + Justification = "To fix this requires rewrite of serializaiton" + )] public static bool ConvertValue(Type type, object? value, out object? convertedValue) { // TODO: Document list of supported values in the SDK. (and grow it as needed) @@ -169,9 +174,9 @@ public static bool ConvertValue(Type type, object? value, out object? convertedV var targetType = typeof(List<>).MakeGenericType(type.GenericTypeArguments); Type listElementType = type.GenericTypeArguments[0]; - _singleValue[0] = valueList.Count; + s_singleValue[0] = valueList.Count; //reuse array to avoid params array allocation - IList ret = (IList)Activator.CreateInstance(targetType, _singleValue); + IList ret = (IList)Activator.CreateInstance(targetType, s_singleValue); foreach (object inputListElement in valueList) { diff --git a/src/Speckle.Sdk/Setup.cs b/src/Speckle.Sdk/Setup.cs index 324c4ac3..8623f30f 100644 --- a/src/Speckle.Sdk/Setup.cs +++ b/src/Speckle.Sdk/Setup.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using Speckle.Sdk.Credentials; using Speckle.Sdk.Helpers; using Speckle.Sdk.Host; @@ -61,7 +60,7 @@ static Setup() foreach (var account in AccountManager.GetAccounts()) { Analytics.AddConnectorToProfile(account.GetHashedEmail(), Application); - Analytics.IdentifyProfile(account.GetHashedEmail(), Application); + Analytics.IdentifyProfile(account.GetHashedEmail()); } return LogBuilder.Initialize( GetUserIdFromDefaultAccount(), diff --git a/src/Speckle.Sdk/Transports/Exceptions.cs b/src/Speckle.Sdk/Transports/Exceptions.cs index 2a9d6183..90cd81b7 100644 --- a/src/Speckle.Sdk/Transports/Exceptions.cs +++ b/src/Speckle.Sdk/Transports/Exceptions.cs @@ -1,5 +1,3 @@ -using Speckle.Sdk.Logging; - namespace Speckle.Sdk.Transports; public class TransportException : SpeckleException diff --git a/src/Speckle.Sdk/Transports/Memory.cs b/src/Speckle.Sdk/Transports/Memory.cs index 14a344b8..a09d5355 100644 --- a/src/Speckle.Sdk/Transports/Memory.cs +++ b/src/Speckle.Sdk/Transports/Memory.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using Speckle.Sdk.Logging; using Speckle.Sdk.Models; @@ -96,7 +95,7 @@ public void SaveObject(string id, string serializedObject) public string? GetObject(string id) { var stopwatch = Stopwatch.StartNew(); - var ret = Objects.TryGetValue(id, out string o) ? o : null; + var ret = Objects.TryGetValue(id, out string? o) ? o : null; stopwatch.Stop(); Elapsed += stopwatch.Elapsed; return ret; diff --git a/src/Speckle.Sdk/Transports/SQLite.cs b/src/Speckle.Sdk/Transports/SQLite.cs index 127d5e22..beba10d6 100644 --- a/src/Speckle.Sdk/Transports/SQLite.cs +++ b/src/Speckle.Sdk/Transports/SQLite.cs @@ -1,6 +1,5 @@ using System.Collections.Concurrent; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Text; using System.Timers; using Microsoft.Data.Sqlite; @@ -282,7 +281,7 @@ public async Task WriteComplete() => /// public bool WriteCompletionStatus => _queue.IsEmpty && !_isWriting; - private void WriteTimerElapsed(object sender, ElapsedEventArgs e) + private void WriteTimerElapsed(object? sender, ElapsedEventArgs e) { _writeTimer.Enabled = false; diff --git a/src/Speckle.Sdk/Transports/ServerUtils/ParallelServerAPI.cs b/src/Speckle.Sdk/Transports/ServerUtils/ParallelServerAPI.cs index b2772553..ff3159ef 100644 --- a/src/Speckle.Sdk/Transports/ServerUtils/ParallelServerAPI.cs +++ b/src/Speckle.Sdk/Transports/ServerUtils/ParallelServerAPI.cs @@ -1,8 +1,6 @@ using System.Collections.Concurrent; using System.Diagnostics; using Speckle.Sdk.Common; -using Speckle.Sdk.Helpers; -using Speckle.Sdk.Logging; using Speckle.Sdk.Serialisation.Utilities; namespace Speckle.Sdk.Transports.ServerUtils; diff --git a/src/Speckle.Sdk/Transports/ServerUtils/ProgressContent.cs b/src/Speckle.Sdk/Transports/ServerUtils/ProgressContent.cs index eddd09d3..82e94c4c 100644 --- a/src/Speckle.Sdk/Transports/ServerUtils/ProgressContent.cs +++ b/src/Speckle.Sdk/Transports/ServerUtils/ProgressContent.cs @@ -15,7 +15,7 @@ public ProgressContent(HttpContent innerContent, Action? progress) innerContent.Headers.CopyTo(Headers); } - protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) + protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) { ProgressStream progressStream = new(stream, _innerContent.Headers.ContentLength, _progress, false); return _innerContent.CopyToAsync(progressStream); diff --git a/src/Speckle.Sdk/Transports/ServerUtils/ProgressStream.cs b/src/Speckle.Sdk/Transports/ServerUtils/ProgressStream.cs index 25591dbf..e6c4bfa7 100644 --- a/src/Speckle.Sdk/Transports/ServerUtils/ProgressStream.cs +++ b/src/Speckle.Sdk/Transports/ServerUtils/ProgressStream.cs @@ -1,6 +1,7 @@ namespace Speckle.Sdk.Transports; -internal class ProgressStream(Stream input, long? streamLength, Action? progress, bool useBuffer) : Stream +internal sealed class ProgressStream(Stream input, long? streamLength, Action? progress, bool useBuffer) + : Stream { private long _position; private readonly Stream _stream = useBuffer ? new BufferedStream(input, 80 * 1024) : input; @@ -35,4 +36,10 @@ public override long Position get => _position; set => throw new NotImplementedException(); } + + protected override void Dispose(bool disposed) + { + _stream.Dispose(); + base.Dispose(disposed); + } } diff --git a/src/Speckle.Sdk/Transports/ServerUtils/ServerAPI.cs b/src/Speckle.Sdk/Transports/ServerUtils/ServerAPI.cs index ac1cb36a..761f5b14 100644 --- a/src/Speckle.Sdk/Transports/ServerUtils/ServerAPI.cs +++ b/src/Speckle.Sdk/Transports/ServerUtils/ServerAPI.cs @@ -235,12 +235,10 @@ public async Task UploadBlobs( multipartFormDataContent.Add(fsc, $"hash:{hash}", fileName); } - using var message = new HttpRequestMessage - { - RequestUri = new Uri($"/api/stream/{streamId}/blob", UriKind.Relative), - Method = HttpMethod.Post, - Content = new ProgressContent(multipartFormDataContent, progress) - }; + using var message = new HttpRequestMessage(); + message.RequestUri = new Uri($"/api/stream/{streamId}/blob", UriKind.Relative); + message.Method = HttpMethod.Post; + message.Content = new ProgressContent(multipartFormDataContent, progress); try { @@ -268,11 +266,9 @@ public async Task DownloadBlobs(string streamId, IReadOnlyList blobIds, { try { - using var blobMessage = new HttpRequestMessage - { - RequestUri = new Uri($"api/stream/{streamId}/blob/{blobId}", UriKind.Relative), - Method = HttpMethod.Get - }; + using var blobMessage = new HttpRequestMessage(); + blobMessage.RequestUri = new Uri($"api/stream/{streamId}/blob/{blobId}", UriKind.Relative); + blobMessage.Method = HttpMethod.Get; using var response = await _client.SendAsync(blobMessage, CancellationToken).ConfigureAwait(false); response.Content.Headers.TryGetValues("Content-Disposition", out IEnumerable? cdHeaderValues); @@ -280,12 +276,9 @@ public async Task DownloadBlobs(string streamId, IReadOnlyList blobIds, var cdHeader = cdHeaderValues.First(); var fileName = cdHeader.Split(s_filenameSeparator, StringSplitOptions.None)[1].TrimStart('"').TrimEnd('"'); - string fileLocation = Path.Combine( - BlobStorageFolder, - $"{blobId.Substring(0, Blob.LocalHashPrefixLength)}-{fileName}" - ); + string fileLocation = Path.Combine(BlobStorageFolder, $"{blobId[..Blob.LocalHashPrefixLength]}-{fileName}"); using var source = new ProgressStream( - await response.Content.ReadAsStreamAsync(), + await response.Content.ReadAsStreamAsync().ConfigureAwait(false), response.Content.Headers.ContentLength, progress, true diff --git a/src/Speckle.Sdk/Transports/ServerV2.cs b/src/Speckle.Sdk/Transports/ServerV2.cs index 15051393..c00d0060 100644 --- a/src/Speckle.Sdk/Transports/ServerV2.cs +++ b/src/Speckle.Sdk/Transports/ServerV2.cs @@ -171,11 +171,11 @@ await api.DownloadObjects( .GetFiles(BlobStorageFolder) .Select(fileName => fileName.Split(Path.DirectorySeparatorChar).Last()) .Where(fileName => fileName.Length > 10) - .Select(fileName => fileName.Substring(0, Blob.LocalHashPrefixLength)) + .Select(fileName => fileName[..Blob.LocalHashPrefixLength]) .ToList(); var newBlobIds = blobIds - .Where(blobId => !localBlobTrimmedHashes.Contains(blobId.Substring(0, Blob.LocalHashPrefixLength))) + .Where(blobId => !localBlobTrimmedHashes.Contains(blobId[..Blob.LocalHashPrefixLength])) .ToList(); await api.DownloadBlobs(StreamId, newBlobIds, OnProgressAction).ConfigureAwait(false); diff --git a/tests/Speckle.LongSendProblem/Program.cs b/tests/Speckle.LongSendProblem/Program.cs index 7e7fdfee..95290d11 100644 --- a/tests/Speckle.LongSendProblem/Program.cs +++ b/tests/Speckle.LongSendProblem/Program.cs @@ -14,24 +14,24 @@ const string OBJECT_ID = "5cbf84a0061172102ef8a66ae914f232"; SetupSpeckle(); -var testData = await GetSampleData(OBJECT_ID); -await SendToSpeckle(testData, modelUrl); +var testData = await GetSampleData(OBJECT_ID).ConfigureAwait(false); +await SendToSpeckle(testData, modelUrl).ConfigureAwait(false); return; static async Task SendToSpeckle(Base testData, Uri modelUrl) { SpeckleLog.Logger.Information("Starting Long Send Test Send"); - var destinationTransport = await GetDestination(modelUrl); + var destinationTransport = await GetDestination(modelUrl).ConfigureAwait(false); - var (res, _) = await Operations.Send(testData, new[] { destinationTransport }); + var (res, _) = await Operations.Send(testData, new[] { destinationTransport }).ConfigureAwait(false); SpeckleLog.Logger.Information("Starting Send was successful: {objectId}", res); } static async Task GetDestination(Uri modelUrl) { StreamWrapper sw = new(modelUrl.ToString()); - var acc = await sw.GetAccount(); + var acc = await sw.GetAccount().ConfigureAwait(false); return new ServerTransport(acc, sw.StreamId); } @@ -40,7 +40,7 @@ static async Task GetSampleData(string objectId) SpeckleLog.Logger.Information("Gathering Sample Data Set"); using SQLiteTransport source = new(SpecklePathProvider.UserApplicationDataPath(), "longsendtest"); MemoryTransport memoryTransport = new(); - return await Operations.Receive(objectId, source, memoryTransport); + return await Operations.Receive(objectId, source, memoryTransport).ConfigureAwait(false); } static void SetupSpeckle() diff --git a/tests/Speckle.Objects.Tests.Unit/ModelPropertySupportedTypes.cs b/tests/Speckle.Objects.Tests.Unit/ModelPropertySupportedTypes.cs index edc29790..f882ffcd 100644 --- a/tests/Speckle.Objects.Tests.Unit/ModelPropertySupportedTypes.cs +++ b/tests/Speckle.Objects.Tests.Unit/ModelPropertySupportedTypes.cs @@ -87,7 +87,11 @@ public void TestObjects() Type propType = prop.PropertyType; Type typeDef = propType.IsGenericType ? propType.GetGenericTypeDefinition() : propType; - Assert.That(_allowedTypes, Does.Contain(typeDef), $"{typeDef} was not in allowedTypes"); + Assert.That( + _allowedTypes, + Does.Contain(typeDef), + $"{typeDef} was not in allowedTypes. (Origin: {type}.{prop.Name})" + ); } } } diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/LegacyAPITests.cs b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/LegacyAPITests.cs index 08590e1d..9fdbd2fb 100644 --- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/LegacyAPITests.cs +++ b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/LegacyAPITests.cs @@ -98,14 +98,6 @@ public async Task StreamCreate() InitServerTransport(); } - [Test, Order(10)] - public async Task StreamsGet() - { - var res = await _myClient.StreamsGet(); - - Assert.That(res, Is.Not.Null); - } - [Test, Order(11)] public async Task StreamGet() { @@ -124,14 +116,6 @@ public async Task IsStreamAccessible() Assert.That(res, Is.True); } - [Test, Order(13)] - public async Task StreamSearch() - { - var res = await _myClient.StreamSearch(_streamId); - - Assert.That(res, Is.Not.Null); - } - [Test, Order(20)] public async Task StreamUpdate() { diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Branches.cs b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Branches.cs deleted file mode 100644 index 00fd0c68..00000000 --- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Branches.cs +++ /dev/null @@ -1,131 +0,0 @@ -using Speckle.Sdk.Api; -using Speckle.Sdk.Credentials; -using Speckle.Sdk.Host; -using Speckle.Sdk.Models; -using Speckle.Sdk.Tests.Unit.Host; - -namespace Speckle.Sdk.Tests.Integration.Api.GraphQL.Legacy.Subscriptions; - -public class Branches : IDisposable -{ - private BranchInfo _branchCreatedInfo; - private BranchInfo _branchDeletedInfo; - private string _branchId; - private BranchInfo _branchUpdatedInfo; - private Client _client; - private string _streamId; - private Account _testUserAccount; - - [SetUp] - public void Setup() - { - TypeLoader.Reset(); - TypeLoader.Initialize(typeof(Base).Assembly, typeof(Point).Assembly); - } - - [OneTimeSetUp] - public async Task OneTimeSetUp() - { - _testUserAccount = await Fixtures.SeedUser(); - _client = new Client(_testUserAccount); - } - - [Test, Order(0)] - public async Task SubscribeBranchCreated() - { - var streamInput = new StreamCreateInput { description = "Hello World", name = "Super Stream 01" }; - - _streamId = await _client.StreamCreate(streamInput); - Assert.That(_streamId, Is.Not.Null); - - _client.SubscribeBranchCreated(_streamId); - _client.OnBranchCreated += Client_OnBranchCreated; - - Thread.Sleep(5000); //let server catch-up - - var branchInput = new BranchCreateInput - { - description = "Just testing branch create...", - name = "awesome-features", - streamId = _streamId - }; - - _branchId = await _client.BranchCreate(branchInput); - Assert.That(_branchId, Is.Not.Null); - - await Task.Run(() => - { - Thread.Sleep(1000); //let client catch-up - Assert.That(_branchCreatedInfo, Is.Not.Null); - Assert.That(_branchCreatedInfo.name, Is.EqualTo(branchInput.name)); - }); - } - - private void Client_OnBranchCreated(object sender, BranchInfo e) - { - _branchCreatedInfo = e; - } - - [Test, Order(1)] - public async Task SubscribeBranchUpdated() - { - _client.SubscribeBranchUpdated(_streamId); - _client.OnBranchUpdated += Client_OnBranchUpdated; - - Thread.Sleep(1000); //let server catch-up - - var branchInput = new BranchUpdateInput - { - description = "Just testing branch bpdate...", - name = "cool-features", - streamId = _streamId, - id = _branchId - }; - - var res = await _client.BranchUpdate(branchInput); - Assert.That(res, Is.True); - - await Task.Run(() => - { - Thread.Sleep(1000); //let client catch-up - Assert.That(_branchUpdatedInfo, Is.Not.Null); - Assert.That(_branchUpdatedInfo.name, Is.EqualTo(branchInput.name)); - }); - } - - private void Client_OnBranchUpdated(object sender, BranchInfo e) - { - _branchUpdatedInfo = e; - } - - [Test, Order(3)] - public async Task SubscribeBranchDeleted() - { - _client.SubscribeBranchDeleted(_streamId); - _client.OnBranchDeleted += Client_OnBranchDeleted; - - Thread.Sleep(1000); //let server catch-up - - var branchInput = new BranchDeleteInput { streamId = _streamId, id = _branchId }; - - var res = await _client.BranchDelete(branchInput); - Assert.That(res, Is.True); - - await Task.Run(() => - { - Thread.Sleep(1000); //let client catch-up - Assert.That(_branchDeletedInfo, Is.Not.Null); - Assert.That(_branchDeletedInfo.id, Is.EqualTo(_branchId)); - }); - } - - private void Client_OnBranchDeleted(object sender, BranchInfo e) - { - _branchDeletedInfo = e; - } - - public void Dispose() - { - _client?.Dispose(); - } -} diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Commits.cs b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Commits.cs deleted file mode 100644 index f0981829..00000000 --- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Commits.cs +++ /dev/null @@ -1,168 +0,0 @@ -using Speckle.Sdk.Api; -using Speckle.Sdk.Credentials; -using Speckle.Sdk.Host; -using Speckle.Sdk.Models; -using Speckle.Sdk.Tests.Unit.Host; -using Speckle.Sdk.Transports; - -namespace Speckle.Sdk.Tests.Integration.Api.GraphQL.Legacy.Subscriptions; - -public class Commits : IDisposable -{ - private Client _client; - private CommitInfo _commitCreatedInfo; - private CommitInfo _commitDeletedInfo; - private string _commitId; - private CommitInfo _commitUpdatedInfo; - private ServerTransport _myServerTransport; - private string _streamId; - private Account _testUserAccount; - - [SetUp] - public void Setup() - { - TypeLoader.Reset(); - TypeLoader.Initialize(typeof(Base).Assembly, typeof(Point).Assembly); - } - - [OneTimeSetUp] - public async Task OneTimeSetUp() - { - _testUserAccount = await Fixtures.SeedUser(); - _client = new Client(_testUserAccount); - } - - private void InitServerTransport() - { - _myServerTransport = new ServerTransport(_testUserAccount, _streamId); - _myServerTransport.Api.CompressPayloads = false; - } - - [Test, Order(0)] - //[Ignore("Ironically, it fails.")] - public async Task SubscribeCommitCreated() - { - var streamInput = new StreamCreateInput { description = "Hello World", name = "Super Stream 01" }; - - _streamId = await _client.StreamCreate(streamInput); - Assert.That(_streamId, Is.Not.Null); - - InitServerTransport(); - - var branchInput = new BranchCreateInput - { - description = "Just testing branch create...", - name = "awesome-features", - streamId = _streamId - }; - - var branchId = await _client.BranchCreate(branchInput); - Assert.That(branchId, Is.Not.Null); - - _client.SubscribeCommitCreated(_streamId); - _client.OnCommitCreated += Client_OnCommitCreated; - - Thread.Sleep(1000); //let server catch-up - - var myObject = new Base(); - var ptsList = new List(); - for (int i = 0; i < 100; i++) - { - ptsList.Add(new Point(i, i, i)); - } - - myObject["Points"] = ptsList; - - var sendResult = await Operations.Send(myObject, _myServerTransport, false); - - var commitInput = new CommitCreateInput - { - streamId = _streamId, - branchName = "awesome-features", - objectId = sendResult.rootObjId, - message = "sending some test points", - sourceApplication = "Tests", - totalChildrenCount = 20 - }; - - _commitId = await _client.CommitCreate(commitInput); - Assert.That(_commitId, Is.Not.Null); - - await Task.Run(() => - { - Thread.Sleep(2000); //let client catch-up - Assert.That(_commitCreatedInfo, Is.Not.Null); - Assert.That(_commitCreatedInfo.message, Is.EqualTo(commitInput.message)); - }); - } - - private void Client_OnCommitCreated(object sender, CommitInfo e) - { - _commitCreatedInfo = e; - } - - [Test, Order(1)] - //[Ignore("Ironically, it fails.")] - public async Task SubscribeCommitUpdated() - { - _client.SubscribeCommitUpdated(_streamId); - _client.OnCommitUpdated += Client_OnCommitUpdated; - - Thread.Sleep(1000); //let server catch-up - - var commitInput = new CommitUpdateInput - { - message = "Just testing commit update...", - streamId = _streamId, - id = _commitId - }; - - var res = await _client.CommitUpdate(commitInput); - Assert.That(res, Is.True); - - await Task.Run(() => - { - Thread.Sleep(2000); //let client catch-up - Assert.That(_commitUpdatedInfo, Is.Not.Null); - Assert.That(_commitUpdatedInfo.message, Is.EqualTo(commitInput.message)); - }); - } - - private void Client_OnCommitUpdated(object sender, CommitInfo e) - { - _commitUpdatedInfo = e; - } - - [Test, Order(3)] - //[Ignore("Ironically, it fails.")] - public async Task SubscribeCommitDeleted() - { - _client.SubscribeCommitDeleted(_streamId); - _client.OnCommitDeleted += Client_OnCommitDeleted; - - Thread.Sleep(1000); //let server catch-up - - var commitInput = new CommitDeleteInput { streamId = _streamId, id = _commitId }; - - var res = await _client.CommitDelete(commitInput); - Assert.That(res, Is.True); - - await Task.Run(() => - { - Thread.Sleep(2000); //let client catch-up - Assert.That(_commitDeletedInfo, Is.Not.Null); - Assert.That(_commitDeletedInfo.id, Is.EqualTo(_commitId)); - }); - } - - private void Client_OnCommitDeleted(object sender, CommitInfo e) - { - _commitDeletedInfo = e; - } - - public void Dispose() - { - _client?.Dispose(); - _myServerTransport?.Dispose(); - } -} diff --git a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Streams.cs b/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Streams.cs deleted file mode 100644 index bec4bbee..00000000 --- a/tests/Speckle.Sdk.Tests.Integration/Api/GraphQL/Legacy/Subscriptions/Streams.cs +++ /dev/null @@ -1,122 +0,0 @@ -using Speckle.Sdk.Api; -using Speckle.Sdk.Credentials; -using Speckle.Sdk.Host; -using Speckle.Sdk.Models; -using Speckle.Sdk.Tests.Unit.Host; - -namespace Speckle.Sdk.Tests.Integration.Api.GraphQL.Legacy.Subscriptions; - -public class Streams : IDisposable -{ - private Client _client; - - private StreamInfo _streamAddedInfo; - private string _streamId; - private StreamInfo _streamRemovedInfo; - private StreamInfo _streamUpdatedInfo; - private Account _testUserAccount; - - [SetUp] - public void Setup() - { - TypeLoader.Reset(); - TypeLoader.Initialize(typeof(Base).Assembly, typeof(Point).Assembly); - } - - [OneTimeSetUp] - public async Task OneTimeSetUp() - { - _testUserAccount = await Fixtures.SeedUser(); - _client = new Client(_testUserAccount); - } - - [Test, Order(0)] - public async Task SubscribeStreamAdded() - { - _client.SubscribeUserStreamAdded(); - _client.OnUserStreamAdded += Client_OnUserStreamAdded; - - Thread.Sleep(1000); //let server catch-up - - var streamInput = new StreamCreateInput { description = "Hello World", name = "Super Stream 01" }; - - var res = await _client.StreamCreate(streamInput); - _streamId = res; - Assert.That(res, Is.Not.Null); - - await Task.Run(() => - { - Thread.Sleep(1000); //let client catch-up - Assert.That(_streamAddedInfo, Is.Not.Null); - Assert.That(_streamAddedInfo.name, Is.EqualTo(streamInput.name)); - }); - } - - private void Client_OnUserStreamAdded(object sender, StreamInfo e) - { - _streamAddedInfo = e; - } - - [Test, Order(1)] - public async Task SubscribeStreamUpdated() - { - _client.SubscribeStreamUpdated(_streamId); - _client.OnStreamUpdated += Client_OnStreamUpdated; - - Thread.Sleep(100); //let server catch-up - - var streamInput = new StreamUpdateInput - { - id = _streamId, - description = "Hello World", - name = "Super Stream 01 EDITED" - }; - - var res = await _client.StreamUpdate(streamInput); - - Assert.That(res, Is.True); - - await Task.Run(() => - { - Thread.Sleep(100); //let client catch-up - Assert.That(_streamUpdatedInfo, Is.Not.Null); - Assert.That(_streamUpdatedInfo.name, Is.EqualTo(streamInput.name)); - }); - } - - private void Client_OnStreamUpdated(object sender, StreamInfo e) - { - _streamUpdatedInfo = e; - } - - [Test, Order(2)] - public async Task SubscribeUserStreamRemoved() - { - _client.SubscribeUserStreamRemoved(); - _client.OnUserStreamRemoved += Client_OnStreamRemoved; - ; - - Thread.Sleep(100); //let server catch-up - - var res = await _client.StreamDelete(_streamId); - - Assert.That(res, Is.True); - - await Task.Run(() => - { - Thread.Sleep(100); //let client catch-up - Assert.That(_streamRemovedInfo, Is.Not.Null); - Assert.That(_streamRemovedInfo.id, Is.EqualTo(_streamId)); - }); - } - - private void Client_OnStreamRemoved(object sender, StreamInfo e) - { - _streamRemovedInfo = e; - } - - public void Dispose() - { - _client?.Dispose(); - } -} diff --git a/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs b/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs index dc27819c..b11a522c 100644 --- a/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs +++ b/tests/Speckle.Sdk.Tests.Performance/Benchmarks/GeneralDeserializerTest.cs @@ -41,6 +41,6 @@ public void Cleanup() public void Dispose() { - // _dataSource.Dispose(); + _dataSource.Dispose(); } } diff --git a/tests/Speckle.Sdk.Tests.Performance/Speckle.Sdk.Tests.Performance.csproj b/tests/Speckle.Sdk.Tests.Performance/Speckle.Sdk.Tests.Performance.csproj index e468ccb4..75c949bc 100644 --- a/tests/Speckle.Sdk.Tests.Performance/Speckle.Sdk.Tests.Performance.csproj +++ b/tests/Speckle.Sdk.Tests.Performance/Speckle.Sdk.Tests.Performance.csproj @@ -5,6 +5,7 @@ net8.0 enable disable + true diff --git a/tests/Speckle.Sdk.Tests.Performance/TestDataHelper.cs b/tests/Speckle.Sdk.Tests.Performance/TestDataHelper.cs index 831a6dbc..523d1ea2 100644 --- a/tests/Speckle.Sdk.Tests.Performance/TestDataHelper.cs +++ b/tests/Speckle.Sdk.Tests.Performance/TestDataHelper.cs @@ -9,7 +9,6 @@ namespace Speckle.Sdk.Tests.Performance; public sealed class TestDataHelper : IDisposable { private static readonly string s_basePath = $"./temp {Guid.NewGuid()}"; - private const string APPLICATION_NAME = "Speckle Performance Tests"; public SQLiteTransport Transport { get; private set; } public string ObjectId { get; private set; } diff --git a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SerializationTests.cs b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SerializationTests.cs index 1d473c54..ea2c9aa5 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SerializationTests.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Api/Operations/SerializationTests.cs @@ -110,19 +110,19 @@ public async Task ListDynamicProp() [Test] public async Task ChunkSerialisation() { - var baseBasedChunk = new DataChunk(); + var baseBasedChunk = new DataChunk() { data = new() }; for (var i = 0; i < 200; i++) { baseBasedChunk.data.Add(new SuperPoint { W = i }); } - var stringBasedChunk = new DataChunk(); + var stringBasedChunk = new DataChunk() { data = new() }; for (var i = 0; i < 200; i++) { stringBasedChunk.data.Add(i + "_hai"); } - var doubleBasedChunk = new DataChunk(); + var doubleBasedChunk = new DataChunk() { data = new() }; for (var i = 0; i < 200; i++) { doubleBasedChunk.data.Add(i + 0.33); diff --git a/tests/Speckle.Sdk.Tests.Unit/Host/HostApplicationTests.cs b/tests/Speckle.Sdk.Tests.Unit/Host/HostApplicationTests.cs index 18379b05..728266c8 100644 --- a/tests/Speckle.Sdk.Tests.Unit/Host/HostApplicationTests.cs +++ b/tests/Speckle.Sdk.Tests.Unit/Host/HostApplicationTests.cs @@ -6,13 +6,13 @@ namespace Speckle.Sdk.Tests.Unit.Host; public class HostApplicationTests { - private static List _hostAppVersion = Enum.GetValues().ToList(); + private static List s_hostAppVersion = Enum.GetValues().ToList(); [Test] - [TestCaseSource("_hostAppVersion")] + [TestCaseSource(nameof(s_hostAppVersion))] public void HostAppVersionParsingTests(HostAppVersion appVersion) { - appVersion.ToString().StartsWith("v").ShouldBeTrue(); + appVersion.ToString().StartsWith('v').ShouldBeTrue(); var version = HostApplications.GetVersion(appVersion); int.Parse(version).ShouldBePositive(); }