1
0
Эх сурвалжийг харах

Merge branch 'master' into IxAsyncCSharp8

Bart J.F. De Smet 7 жил өмнө
parent
commit
347b5aacbb

+ 27 - 2
.editorconfig

@@ -7,6 +7,7 @@ root = true
 # Don't use tabs for indentation.
 [*]
 indent_style = space
+trim_trailing_whitespace = true
 # (Please don't specify an indent_size here; that has too many unintended consequences.)
 
 # Code files
@@ -27,6 +28,10 @@ indent_size = 2
 [*.{yaml,yml}]
 indent_size = 2
 
+# Powershell files
+[*.ps1]
+indent_size = 2
+
 # JSON files
 [*.json]
 indent_size = 2
@@ -69,7 +74,13 @@ dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
 dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
 dotnet_style_prefer_conditional_expression_over_return = false
 dotnet_style_prefer_conditional_expression_over_assignment = false
-dotnet_style_prefer_auto_properties = true
+dotnet_style_prefer_auto_properties = true:suggestion
+
+# Parentheses
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
 
 # Accessibility modifiers
 dotnet_style_require_accessibility_modifiers = always:suggestion
@@ -163,6 +174,12 @@ dotnet_naming_style.pascal_case_and_prefix_with_I_style.capitalization
 
 # CSharp code style settings:
 [*.cs]
+# Modifier order
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
+
+# Code block
+csharp_prefer_braces = false:none
+
 # Indentation preferences
 csharp_indent_block_contents = true
 csharp_indent_braces = false
@@ -234,4 +251,12 @@ csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
 csharp_space_between_method_declaration_name_and_open_parenthesis = false
 csharp_space_between_method_declaration_parameter_list_parentheses = false
 csharp_space_between_parentheses = false
-csharp_space_between_square_brackets = false
+csharp_space_between_square_brackets = false
+
+
+
+
+
+
+
+

+ 1 - 1
Ix.NET/Source/Directory.build.props

@@ -5,7 +5,7 @@
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <Authors>.NET Foundation and Contributors</Authors>
     <PackageIconUrl>http://go.microsoft.com/fwlink/?LinkId=261274</PackageIconUrl>
-    <PackageProjectUrl>http://go.microsoft.com/fwlink/?LinkId=261273</PackageProjectUrl>
+    <PackageProjectUrl>https://github.com/dotnet/reactive</PackageProjectUrl>
     <PackageLicenseUrl>https://raw.githubusercontent.com/Reactive-Extensions/Rx.NET/master/Ix.NET/Source/license.txt</PackageLicenseUrl>
     <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
     <SignAssembly>true</SignAssembly>

+ 2 - 0
Ix.NET/Source/Ix.NET.sln

@@ -7,10 +7,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{87534290-A
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B733D97A-F1ED-4FC3-BF8E-9AC47A89DE96}"
 	ProjectSection(SolutionItems) = preProject
+		..\..\.editorconfig = ..\..\.editorconfig
 		..\..\azure-pipelines.ix.yml = ..\..\azure-pipelines.ix.yml
 		CodeCoverage.runsettings = CodeCoverage.runsettings
 		Directory.build.props = Directory.build.props
 		Directory.build.targets = Directory.build.targets
+		global.json = global.json
 		NuGet.Config = NuGet.Config
 		version.json = version.json
 	EndProjectSection

+ 12 - 0
README.md

@@ -132,6 +132,18 @@ System.Reactive is part of the [.NET Foundation](https://www.dotnetfoundation.or
         <a href="https://github.com/onovotny">Oren Novotny</a>
         <p>New York, USA</p>
       </td>
+      <td align="center" valign="top">
+        <img width="150" height="150" src="https://github.com/akarnokd.png?s=150">
+        <br>
+        <a href="https://github.com/akarnokd">David Karnok</a>
+        <p>Budapest, Hungary</p>
+      </td>
+      <td align="center" valign="top">
+        <img width="150" height="150" src="https://github.com/danielcweber.png?s=150">
+        <br>
+        <a href="https://github.com/danielcweber">Daniel C. Weber</a>
+        <p>Aachen, Germany</p>
+      </td>
      </tr>
   </tbody>
 </table>

+ 1 - 1
Rx.NET/Source/Directory.build.props

@@ -6,7 +6,7 @@
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <Authors>.NET Foundation and Contributors</Authors>
     <PackageIconUrl>http://go.microsoft.com/fwlink/?LinkId=261274</PackageIconUrl>
-    <PackageProjectUrl>http://go.microsoft.com/fwlink/?LinkId=261273</PackageProjectUrl>
+    <PackageProjectUrl>https://github.com/dotnet/reactive</PackageProjectUrl>
     <PackageLicenseUrl>http://go.microsoft.com/fwlink/?LinkID=261272</PackageLicenseUrl>
     <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>    
     <DebugType>embedded</DebugType>

+ 2 - 2
Rx.NET/Source/facades/System.Reactive.Compatibility.nuspec

@@ -7,7 +7,7 @@
         <authors>.NET Foundation and Contributors</authors>
         <owners>Microsoft,RxTeam</owners>
         <licenseUrl>http://go.microsoft.com/fwlink/?LinkID=261272</licenseUrl>
-        <projectUrl>http://go.microsoft.com/fwlink/?LinkId=261273</projectUrl>
+        <projectUrl>https://github.com/dotnet/reactive</projectUrl>
         <iconUrl>http://go.microsoft.com/fwlink/?LinkId=261274</iconUrl>
         <requireLicenseAcceptance>false</requireLicenseAcceptance>
         <description>Reactive Extensions (Rx) Compatibility Library for enabling v3 apps to work with v4</description>
@@ -45,4 +45,4 @@
         </dependencies>
     </metadata>
     <files />
-</package>
+</package>

+ 29 - 5
Rx.NET/Source/src/System.Reactive/Linq/Observable/Finally.cs

@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information. 
 
 using System.Reactive.Disposables;
+using System.Threading;
 
 namespace System.Reactive.Linq.ObservableImpl
 {
@@ -24,7 +25,6 @@ namespace System.Reactive.Linq.ObservableImpl
         internal sealed class _ : IdentitySink<TSource>
         {
             private readonly Action _finallyAction;
-
             private IDisposable _sourceDisposable;
 
             public _(Action finallyAction, IObserver<TSource> observer)
@@ -35,19 +35,43 @@ namespace System.Reactive.Linq.ObservableImpl
 
             public override void Run(IObservable<TSource> source)
             {
-                Disposable.SetSingle(ref _sourceDisposable, source.SubscribeSafe(this));
+                var d = source.SubscribeSafe(this);
+
+                if (Interlocked.CompareExchange(ref _sourceDisposable, d, null) == BooleanDisposable.True)
+                {
+                    // The Dispose(bool) methode was already called before the
+                    // subscription could be assign, hence the subscription
+                    // needs to be diposed here and the action needs to be invoked.
+                    try
+                    {
+                        d.Dispose();
+                    }
+                    finally
+                    {
+                        _finallyAction();
+                    }
+                }
             }
 
             protected override void Dispose(bool disposing)
             {
+                base.Dispose(disposing);
+
                 if (disposing)
                 {
-                    if (Disposable.TryDispose(ref _sourceDisposable))
+                    var d = Interlocked.Exchange(ref _sourceDisposable, BooleanDisposable.True);
+                    if (d != BooleanDisposable.True && d != null)
                     {
-                        _finallyAction();
+                        try
+                        {
+                            d.Dispose();
+                        }
+                        finally
+                        {
+                            _finallyAction();
+                        }
                     }
                 }
-                base.Dispose(disposing);
             }
         }
     }

+ 9 - 5
Rx.NET/Source/src/System.Reactive/Linq/Observable/Using.cs

@@ -34,33 +34,37 @@ namespace System.Reactive.Linq.ObservableImpl
             public void Run(Using<TSource, TResource> parent)
             {
                 var source = default(IObservable<TSource>);
+                var disposable = Disposable.Empty;
                 try
                 {
                     var resource = parent._resourceFactory();
                     if (resource != null)
                     {
-                        Disposable.SetSingle(ref _disposable, resource);
+                        disposable = resource;
                     }
 
                     source = parent._observableFactory(resource);
                 }
                 catch (Exception exception)
                 {
-                    SetUpstream(Observable.Throw<TSource>(exception).SubscribeSafe(this));
-
-                    return;
+                    source = Observable.Throw<TSource>(exception);
                 }
 
+                // It is important to set the disposable resource after
+                // Run(). In the synchronous case this would else dispose
+                // the the resource before the source subscription.
                 Run(source);
+                Disposable.SetSingle(ref _disposable, disposable);
             }
 
             protected override void Dispose(bool disposing)
             {
+                base.Dispose(disposing);
+
                 if (disposing)
                 {
                     Disposable.TryDispose(ref _disposable);
                 }
-                base.Dispose(disposing);
             }
         }
     }

+ 4 - 1
Rx.NET/Source/src/System.Reactive/Linq/Observable/Zip.cs

@@ -524,7 +524,10 @@ namespace System.Reactive.Linq.ObservableImpl
 
         public override void OnCompleted()
         {
-            Dispose();
+            // Calling Dispose() here would clear the queue prematurely.
+            // We only need to dispose the IDisposable of the upstream,
+            // which is done by SafeObserver.Dispose(bool).
+            base.Dispose(true);
 
             lock (_gate)
             {

+ 0 - 0
Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Aliases.approved.txt → Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Aliases.approved.cs


+ 0 - 0
Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.approved.txt → Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Core.approved.cs


+ 0 - 0
Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Testing.approved.txt → Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.Testing.approved.cs


+ 3 - 3
Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Api/ApiApprovalTests.cs

@@ -30,21 +30,21 @@ namespace ReactiveTests.Tests.Api
         public void Core()
         {
             var publicApi = GeneratePublicApi(typeof(System.Reactive.Unit).Assembly);
-            Approvals.Verify(publicApi);
+            Approvals.Verify(new ApprovalTextWriter(publicApi, "cs"));
         }
 
         [Fact]
         public void Aliases()
         {
             var publicApi = GeneratePublicApi(typeof(System.Reactive.Observable.Aliases.QueryLanguage).Assembly);
-            Approvals.Verify(publicApi);
+            Approvals.Verify(new ApprovalTextWriter(publicApi, "cs"));
         }
 
         [Fact]
         public void Testing()
         {
             var publicApi = GeneratePublicApi(typeof(Microsoft.Reactive.Testing.TestScheduler).Assembly);
-            Approvals.Verify(publicApi);
+            Approvals.Verify(new ApprovalTextWriter(publicApi, "cs"));
         }
 
         private string GeneratePublicApi(Assembly assembly)

+ 14 - 0
Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Tests.System.Reactive.ApiApprovals.csproj

@@ -8,6 +8,20 @@
     <Optimize>false</Optimize>
   </PropertyGroup>
 
+  <ItemGroup>
+    <Compile Remove="Api\ApiApprovalTests.Aliases.approved.cs" />
+    <Compile Remove="Api\ApiApprovalTests.Core.approved.cs" />
+    <Compile Remove="Api\ApiApprovalTests.Testing.approved.cs" />
+    
+    <None Include="Api\ApiApprovalTests.Aliases.approved.cs" />
+    <None Include="Api\ApiApprovalTests.Core.approved.cs" />
+    <None Include="Api\ApiApprovalTests.Testing.approved.cs" />
+    
+    <None Include="Api\ApiApprovalTests.Aliases.approved.cs" />
+    <None Include="Api\ApiApprovalTests.Core.approved.cs" />
+    <None Include="Api\ApiApprovalTests.Testing.approved.cs" />
+  </ItemGroup>
+
   <ItemGroup>
     <Content Include="xunit.runner.json">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

+ 1 - 0
Rx.NET/Source/tests/Tests.System.Reactive/Tests/LicenseHeaderTest.cs

@@ -53,6 +53,7 @@ namespace Tests.System.Reactive.Tests
                     || file.Contains("AssemblyInfo.cs")
                     || file.Contains(".Designer.cs")
                     || file.Contains(".Generated.cs")
+                    || file.Contains(".approved.cs")
                     || file.Contains("Uwp.DeviceRunner")
                 )
                 {

+ 44 - 0
Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/FinallyTest.cs

@@ -3,6 +3,7 @@
 // See the LICENSE file in the project root for more information. 
 
 using System;
+using System.Reactive;
 using System.Reactive.Linq;
 using Microsoft.Reactive.Testing;
 using Xunit;
@@ -142,5 +143,48 @@ namespace ReactiveTests.Tests
             );
         }
 
+        [Fact]
+        public void Finally_DisposeOrder_Empty()
+        {
+            var order = "";
+            Observable
+                .Empty<Unit>()
+                .Finally(() => order += "1")
+                .Finally(() => order += "2")
+                .Finally(() => order += "3")
+                .Subscribe();
+
+            Assert.Equal("123", order);
+        }
+
+        [Fact]
+        public void Finally_DisposeOrder_Return()
+        {
+            var order = "";
+            Observable
+                .Return(Unit.Default)
+                .Finally(() => order += "1")
+                .Finally(() => order += "2")
+                .Finally(() => order += "3")
+                .Subscribe();
+
+            Assert.Equal("123", order);
+        }
+
+        [Fact]
+        public void Finally_DisposeOrder_Never()
+        {
+            var order = "";
+            var d = Observable
+                .Never<Unit>()
+                .Finally(() => order += "1")
+                .Finally(() => order += "2")
+                .Finally(() => order += "3")
+                .Subscribe();
+
+            d.Dispose();
+
+            Assert.Equal("123", order);
+        }
     }
 }

+ 32 - 0
Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/UsingTest.cs

@@ -3,6 +3,8 @@
 // See the LICENSE file in the project root for more information. 
 
 using System;
+using System.Reactive;
+using System.Reactive.Disposables;
 using System.Reactive.Linq;
 using Microsoft.Reactive.Testing;
 using ReactiveTests.Dummies;
@@ -295,5 +297,35 @@ namespace ReactiveTests.Tests
             );
         }
 
+        [Fact]
+        public void Using_NestedCompleted()
+        {
+            var order = "";
+
+            Observable.Using(() => Disposable.Create(() => order += "3"),
+                _ => Observable.Using(() => Disposable.Create(() => order += "2"),
+                    __ => Observable.Using(() => Disposable.Create(() => order += "1"),
+                        ___ => Observable.Return(Unit.Default))))
+                .Finally(() => order += "4")
+                .Subscribe();
+
+            Assert.Equal("1234", order);
+        }
+
+        [Fact]
+        public void Using_NestedDisposed()
+        {
+            var order = "";
+
+            Observable.Using(() => Disposable.Create(() => order += "3"),
+                _ => Observable.Using(() => Disposable.Create(() => order += "2"),
+                    __ => Observable.Using(() => Disposable.Create(() => order += "1"),
+                        ___ => Observable.Never<Unit>())))
+                .Finally(() => order += "4")
+                .Subscribe()
+                .Dispose();
+
+            Assert.Equal("1234", order);
+        }
     }
 }

+ 10 - 6
Rx.NET/Source/tests/Tests.System.Reactive/Tests/Linq/Observable/ZipTest.cs

@@ -4462,13 +4462,17 @@ namespace ReactiveTests.Tests
         [Fact]
         public void Zip3WithImmediateReturn()
         {
-            Observable.Zip<Unit, Unit, Unit, Unit>(
-                Observable.Return(Unit.Default),
-                Observable.Return(Unit.Default),
-                Observable.Return(Unit.Default),
-                (_, __, ___) => Unit.Default
+            int result = 0;
+
+            Observable.Zip<int, int, int, int>(
+                Observable.Return(1),
+                Observable.Return(2),
+                Observable.Return(4),
+                (a, b, c) => a + b + c
             )
-            .Subscribe(_ => { });
+            .Subscribe(v => result = v);
+
+            Assert.Equal(7, result);
         }
 
         [Fact]

+ 16 - 4
azure-pipelines.ix.yml

@@ -9,6 +9,17 @@ trigger:
       - .editorconfig
       - azure-pipelines.ix.yml
 
+pr:
+  branches:
+    include:
+      - master
+      - rel/*
+  paths:
+    include:
+      - Ix.NET/Source/*
+      - .editorconfig
+      - azure-pipelines.ix.yml
+
 pool:
   vmImage: vs2017-win2016
 
@@ -22,11 +33,9 @@ steps:
     custom: tool
     arguments: install --tool-path . nbgv
   displayName: Install NBGV tool
-  condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
 
 - script: nbgv cloud -p Ix.NET\Source
   displayName: Set Version
-  condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
 
 - task: DotNetCoreCLI@2
   inputs:
@@ -43,7 +52,11 @@ steps:
     projects: Ix.NET/Source/**/*.Tests.csproj
     arguments: -c $(BuildConfiguration) --collect:"Code Coverage" -s $(System.DefaultWorkingDirectory)/Ix.NET/Source/CodeCoverage.runsettings /p:DebugType=Full 
   displayName: Run Tests
-  
+
+- task: whitesource.ws-bolt.bolt.wss.WhiteSource Bolt@18
+  displayName: 'WhiteSource Bolt'
+  enabled: false
+
 - task: PowerShell@2
   displayName: Authenticode Sign Packages
   inputs:
@@ -59,4 +72,3 @@ steps:
     PathtoPublish: $(Build.ArtifactStagingDirectory)\artifacts
     ArtifactName: artifacts
     publishLocation: Container
-  condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))

+ 17 - 5
azure-pipelines.rx.yml

@@ -9,6 +9,17 @@ trigger:
       - .editorconfig
       - azure-pipelines.rx.yml
 
+pr:
+  branches:
+    include:
+    - master
+    - rel/*
+  paths:
+    include:
+      - Rx.NET/Source/*
+      - .editorconfig
+      - azure-pipelines.rx.yml
+
 pool:
   vmImage: vs2017-win2016
 
@@ -23,11 +34,9 @@ steps:
     custom: tool
     arguments: install --tool-path . nbgv
   displayName: Install NBGV tool
-  condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
 
 - script: nbgv cloud -a -p Rx.NET\Source
   displayName: Set Version
-  condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
 
 - task: MSBuild@1
   displayName: Build System.Reactive.sln
@@ -43,8 +52,7 @@ steps:
   inputs:
     command: custom
     arguments: pack Rx.NET/Source/facades/System.Reactive.Compatibility.nuspec -Version $(NBGV_NuGetPackageVersion) -MinClientVersion 2.12 -NoPackageAnalysis -outputdirectory $(Build.ArtifactStagingDirectory)\artifacts
-  condition: eq(variables['system.pullrequest.isfork'], false)
-
+  
 - task: MSBuild@1
   displayName: Build for Test (ppdb) workaround
   inputs:
@@ -67,6 +75,10 @@ steps:
     projects: Rx.NET/Source/tests/Tests.System.Reactive.ApiApprovals/Tests.System.Reactive.ApiApprovals.csproj
     arguments: -c $(BuildConfiguration) --no-build --no-restore 
   displayName: Run Api Approvals Tests
+
+- task: whitesource.ws-bolt.bolt.wss.WhiteSource Bolt@18
+  displayName: 'WhiteSource Bolt'
+  enabled: false
   
 - task: PowerShell@2
   displayName: Authenticode Sign Packages
@@ -83,4 +95,4 @@ steps:
     PathtoPublish: $(Build.ArtifactStagingDirectory)\artifacts
     ArtifactName: artifacts
     publishLocation: Container
-  condition: and(succeeded(), eq(variables['system.pullrequest.isfork'], false))
+