Skip to content
yiquanshui edited this page Dec 22, 2023 · 2 revisions

Introduction

Hello and thank you for contributing to dotnet/reactive. Before you proceed with your contribution:

  • Please make sure your contribution is in line with the project's licensing model and your employment allows you to contribute to open source.

  • Please sign the Contributor License Agreement in case the CLA bot asks you for being a new contributor.

  • Please make sure you target the master branch when creating the PR.

Forking and branching

In order to contribute to the project, you have to fork it, make changes in your local fork and branch, then propose a so-called Pull Request. The following sections will guide you through the steps:

1. Fork dotnet/reactive (once)

On GitHub, navigate to dotnet/reactive and create a fork if you haven't done so:

image

2. Clone the origin/master branch (once)

Usually, the master branch gets outdated in user forks, therefore, it is highly recommended you checkout the project's git repository, then add a new reference to your fork. (Unfortunately, this has to be done from command line because Visual Studio does not support adding remotes from the UI.)

git clone https://github.com/dotnet/reactive.git

cd reactive

git remote add myfork https://github.com/user/reactive.git

Replace user with your user name.

3. Refresh the master branch

In Visual Studio, right click on the branch icon on the lower right and select Pull:

image

For command line:

git pull origin master

4. Create your branch.

In the same popup menu, select New branch...,

image

then specify a custom name indicating what you try to do within, then click Create branch:

image

For command line

git checkout -b [name_of_your_new_branch]

5. Apply your modifications

Now you are in your own branch and you can perform the changes you wanted on the appropriate subproject. dotnet/reactive has several solution files, of which the two most important ones are System.Reactive.sln for Rx.NET and Ix.NET.sln for Ix and Async Ix:

image

The layout of the projects can be confusing at times, so here are some hints where to find the various components usually targeted for contributions:

System.Reactive solution

  • The standard operator descriptions and documentations are located in the System.Reactive subproject under the Linq directory in files named like Observable.X.cs where X is the name of the operator category. If you don't know which category an operator belongs to, open one such file, then use the method dropdown to navigate to the correct one.
  • Operators are intercepted through an interface indirection. Each operator method must be listed in Linq/IQueryLanguage.cs and their implementation invoked in Linq/QueryLanguage.X.cs where X is again the operator category.
  • The concrete operator implementations should be placed in their own file named after the operator (overloads can be toghether) under the Linq/Observable/ directory.
  • Tests are also placed in individual files based on the operator name and can be found in the Tests.System.Reactive subproject under the Tests/Linq/Observable/ directory.

Ix.NET solution

  • The project does not host implementations for the standard System.Linq operators anymore as these have been moved into the CoreFx library some time ago.
  • Extra operators are implemented in their own file in the System.Interactive subproject under the Linq/Operators directory. However, there is no separate main partial class but each operator file is a partial class of EnumerableEx. Each such partial class hosts the entire operator implementation. Individual operator test files are located in the System.Interactive.Tests subproject under the System/Linq/Operators directory.
  • Standard async operators are implemented in their own file in the System.Linq.Async subproject under the Linq/Operators directory. Each file is a partial class of Linq/AsyncEnumerable.cs . Each such partial class hosts the entire operator implementation. Individual operator test files are located in the System.Linq.Async.Tests subproject under the System/Linq/Operators directory.
  • Extra async operators are implemented in their own file in the System.Interactive.Async subproject under the Linq/Operators directory. Each file is a partial class of Linq/AsyncEnumerableEx.cs . Each such partial class hosts the entire operator implementation. Individual operator test files are located in the System.Interactive.Async.Tests subproject under the System/Linq/Operators directory.

Here are some general hints to consider:

  • Changing documentation of an operator. If you are fixing or adding documentation, please make sure both the Observable.X.cs and Qbservable.X.cs files get an update for Rx.NET.

  • Fixing or adding an operator. Please include unit tests that verify the behavior of the new feature. Please make sure the code coverage is reasonably high with the new code. Depending on the feature, you may want to include actual multi-threaded test cases to verify the correct async behavior, however, please be mindful of the time such tests take and try to stay under a few seconds.

  • Adding an operator. Including all above, you'll have to update the API approvals file in Rx.NET\Source\tests\Tests.System.Reactive.ApiApprovals\Api\ApiApprovalTests.Core.approved.cs

  • Please run all tests of the solution. This makes sure nothing broke accidentally. Some unit tests may fail though:

    • ApiApprovalTests: you'll have to add the new method signatures to ApiApprovalTests.Core.approved.cs
    • ArgumentValidationTest: operators on Observable and ObservableEx have to be implemented with null checks for their parameters. The test failure message should indicate which overloads and arguments are missing validation code.
    • LicenseHeaderTest: new files should include the standard license header of the project (including the empty newline after the text):
// Licensed to the .NET Foundation under one or more agreements.",
// The .NET Foundation licenses this file to you under the Apache 2.0 License.",
// See the LICENSE file in the project root for more information.",

6. Commit your changes

Once you are done with the changes, you must commit them so git knows about it. Either use the Commit button (pencil icon) on the bottom right corner:

image

then specify the short commit message:

image

The pick Commit All. (Please do not pick any of the other options there as the push has to be manually routed to your branch, see the next step.)

or from command line

git commit -m "short change description here"

7. Push the changes

In Visual Studio, pick the Unpushed commit (up arrow) on the bottom right to begin the process:

image

In the synchronization dialog, select the Push option from the menu, then select your remote name you specified in step 2) (myfork), then select the branch name you gave in step 4)

image

or on the command line

git push myfork name_of_your_new_branch

Once ready, press the Push button and you are done locally. Now you have to propose these changes by opening a pull request on GitHub.

Opening a Pull Request

When you are ready to submit your changes, go to the Pull requests page and once your branch pops up, click on the green "Compare & Pull request"

image

Then, depending on your kind of your contribution, please read the welcome text or the following related subsection and fill in the comments textbox:

image

When you write the PR description, please consider the following points depending on the type of your contribution:

Bugfix

  • Please describe what and how the bug manifested itself and what kind of fix did you implement. Practically, you are writing these descriptions for the search engines so others can find the resolution easier.

  • Please reference the related issue(s) to the original bug report (example: Fixes #X, Resolves #X). Note that some behaviors are by design and are not bugs. If you are unsure, please open an issue first.

  • Please include the relevant unit test(s) that verify the fix works. It is recommended you write the unit test(s) first to see they failed before your fix; however, there is no need to post a PR to demonstrate this failure stage. Please post in a state where the issue is resolved.

Enhancement

  • Please consider opening an issue first to discuss the kind and impact of the enhancement, if such an issue doesn't exist yet. Also please check if there was a consensus about accepting such an enhancement.
  • Please describe how, what and why the enhancement is implemented. Practically, you are writing these descriptions for the search engines so others can find the change details easier.
  • Please reference the related issue(s) to the original issue report (example: Fixes #X, Resolves #X).
  • Please include the relevant unit test(s) or benchmark(s) that show or verify the enhancement works.

Feature request

  • We strongly recommend opening an issue first to discuss the nature and impact of the request first. If such an issue already exists, please check if there was a consensus and approval for accepting a contribution.
  • Please describe what request is about, how it works in general and what possible corner cases it or the user should consider. Please include some basic usage examples of the important components and/or overloads. Practically, you are writing these descriptions for the search engines so others can find out about the new feature easier.
  • Please reference the related issue(s) to the original issue report (example: Resolves #X).
  • Please include unit tests that verify the behavior of the new feature. Please make sure the code coverage is reasonably high with the new code.
  • Depending on the feature, you may want to include actual multi-threaded test cases to verify the correct async behavior, however, please be mindful of the time such tests take and try to stay under a few seconds.