Difference between revisions of "Contributing to Phobos"

From D Wiki
Jump to: navigation, search
(removed checks)
m (Fix issue -> Fix Bugzilla issue)
 
(27 intermediate revisions by 4 users not shown)
Line 1: Line 1:
= Guidelines for Contributing =
 
 
 
Welcome to the D community and thanks for your interest in contributing!
 
Welcome to the D community and thanks for your interest in contributing!
 +
If you need help you can ask questions on <code>#d</code> IRC channel on libera.chat ([https://kiwiirc.com/nextclient/irc.libera.chat/d web interface]) or on [https://forum.dlang.org/ our forum].
  
== Quick links ==
+
For a lists of ideas on how to contribute, please see [[Get_involved|Get involved]]. This document provides advice on making a good pull request to Phobos.
 
 
* Fork [https://github.com/D-Programming-Language/phobos on Github]
 
* Use our [http://d.puremagic.com/issues/ Bugzilla bug tracker]
 
* Follow the [http://dlang.org/dstyle.html D style]
 
* Participate in [http://forum.dlang.org/ our forum]
 
* Ask questions on <code>#d</code> IRC channel on freenode.org ([https://kiwiirc.com/client/irc.freenode.net/d web interface])
 
* Review Phobos additions in the [[Review Queue]]
 
  
= How to make a good submission? =
+
== Guidelines for contributing to Phobos ==
  
 
The usual workflow is:
 
The usual workflow is:
  
# [https://help.github.com/articles/fork-a-repo/ Fork] [https://github.com/D-Programming-Language/phobos Phobos] on Github
+
# [https://docs.github.com/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo Fork] [https://github.com/dlang/phobos Phobos] on GitHub
 
# Create your [https://github.com/Kunena/Kunena-Forum/wiki/Create-a-new-branch-with-git-and-manage-branches own branch]
 
# Create your [https://github.com/Kunena/Kunena-Forum/wiki/Create-a-new-branch-with-git-and-manage-branches own branch]
# [Starting as a Contributor#Building_D Work|locally]] on your new feature or fix (see the tips below)
+
# [[Starting as a Contributor#Building_from_source|Work locally]] on your new feature or fix (see the tips below)
# [[#tests|Test]] your improvements locally
+
# [[#Unittest_phobos|Test]] your improvements locally
# Submit your [https://help.github.com/articles/creating-a-pull-request/ pull request] (PR)
+
# Submit your [https://docs.github.com/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request pull request] (PR)
  
 +
You can find [[Starting_as_a_Contributor#Building_from_source|build instructions here]].
 
Below is a list of tips and checks that you should consider before opening your pull request:
 
Below is a list of tips and checks that you should consider before opening your pull request:
 +
 +
== Unittest <tt>phobos</tt> ==
 +
 +
This section explains commands which are commonly used to test the D standard library <tt>phobos</tt>.
 +
 +
=== Full build ===
 +
 +
If you want to work on phobos itself, you need to run unittests&mdash;either for the full library, a package, or a module. To unittest the entire library:
 +
 +
<syntaxhighlight lang=bash>
 +
make -j16 -f posix.mak unittest
 +
</syntaxhighlight>
 +
 +
Adjust the parameter passed to <tt>-j</tt> depending on your machine (beefier machines support larger parameters). This command unittests <tt>phobos</tt> in both debug and release mode. To only test one of them, add <tt>BUILD=debug</tt> or <tt>BUILD=release</tt> to the command line, for example:
 +
 +
<syntaxhighlight lang=bash>
 +
make -j16 -f posix.mak BUILD=debug unittest
 +
</syntaxhighlight>
 +
 +
Specifying <tt>BUILD</tt> makes unittesting faster so it is recommended in iterative development. Just make sure both debug and release builds are tested before e.g. submitting a pull request.
 +
 +
=== Test a single Phobos module ===
 +
 +
While changing one specific package or module, it's useful to be able to only unittest that particular entity. The following two commands only unittest (in debug mode) the <tt>std.algorithm</tt> package:
 +
 +
<syntaxhighlight lang=bash>
 +
make -j16 -f posix.mak BUILD=debug std/algorithm.test
 +
</syntaxhighlight>
 +
 +
Several modules, packages, or mix thereof may be specified for testing in the same command line. For example, this command also tests (and also in debug mode) the <tt>std.algorithm</tt> package and the <tt>std.conv</tt> module, with better parallelism:
 +
 +
<syntaxhighlight lang=bash>
 +
make -j16 -f posix.mak BUILD=debug std/algorithm.test std/conv.test
 +
</syntaxhighlight>
 +
 +
=== Test a single module without rebuilding Phobos ===
 +
 +
You can test a module directly with <tt>rdmd</tt>:
 +
 +
<syntaxhighlight lang=bash>
 +
rdmd --compiler=~/dlang/dmd/generated/linux/release/64/dmd -unittest -main std/algorithm/sorting.d
 +
</syntaxhighlight>
 +
 +
(If you are on a different platform, replace <tt>linux></tt> with your respective platform)
 +
 +
However, be aware that this method doesn't recompile the Phobos library and thus only checks the executed file.
 +
Thus you should only use this for fast builds on small changes.
 +
 +
== Run CI checks ==
 +
 +
The auto-tester will fail your PR if your changes contain trailing whitespace or incorrect line endings. You can run this test locally with the command:
 +
 +
<syntaxhighlight lang=bash>
 +
make -j16 -f posix.mak checkwhitespace
 +
</syntaxhighlight>
 +
 +
CircleCi will also run various checks for the [http://dlang.org/dstyle.html DStyle] and ensures that every example is runnable on <tt>dlang.org</tt>.
 +
You can run this test locally with:
 +
 +
<syntaxhighlight lang=bash>
 +
make -f posix.mak style
 +
</syntaxhighlight>
 +
 +
== Code ==
  
 
=== Code style ===
 
=== Code style ===
Line 28: Line 85:
 
* Stick to the [http://dlang.org/dstyle.html style guide]? (e.g. braces in their own lines (allman style) or white spaces between operators)
 
* Stick to the [http://dlang.org/dstyle.html style guide]? (e.g. braces in their own lines (allman style) or white spaces between operators)
 
* Avoid unnecessarily importing other Phobos modules
 
* Avoid unnecessarily importing other Phobos modules
* Try to not require a garbage collector (this is not a must)
+
* Try to not require the garbage collector (this is not a must)
 
* Avoid code duplication
 
* Avoid code duplication
* Maximal <code>@nogc</code>, <code>@safe</code>, <code>pure</code>, <code>nothrow</code> in ''non-templated'' functions
 
* Don't add <code>@nogc</code>, <code>@safe</code>, <code>pure</code>, <code>nothrow</code> attributes to ''templated'' functions - let the compiler infer it! However add unittest checks for these attributes if possible (e.g. <code>pure nothrow @nogc @safe unittest { ... }</code>)
 
 
* Avoid using <code>auto</code> as return type wherever possible (makes the documentation easier to read)
 
* Avoid using <code>auto</code> as return type wherever possible (makes the documentation easier to read)
 
* Use <code>static</code> nested structs for ranges (aka [[Voldemort types]]) and thus store function parameters explicitly in the nested struct
 
* Use <code>static</code> nested structs for ranges (aka [[Voldemort types]]) and thus store function parameters explicitly in the nested struct
 
* Avoid <code>unittest</code> in templates (it will generate a new unittest for each instance) - put your tests outside
 
* Avoid <code>unittest</code> in templates (it will generate a new unittest for each instance) - put your tests outside
 +
* Do overflow checks when computing sizes for <code>malloc</code> and <code>realloc</code>
  
 
=== Code advice ===
 
=== Code advice ===
Line 54: Line 110:
 
** for Windows have a look at [[Starting as a Contributor#Windows_2|building Phobos under windows]])
 
** for Windows have a look at [[Starting as a Contributor#Windows_2|building Phobos under windows]])
 
* Do your tests cover all cases? (you can check code coverage in the resulting <code>module.lst</code> of <code>rdmd -cov -main -unittest module.d</code>)
 
* Do your tests cover all cases? (you can check code coverage in the resulting <code>module.lst</code> of <code>rdmd -cov -main -unittest module.d</code>)
 +
* Make sure the new code compiles with the -dip1000 switch.
  
=== Review process ===
+
== Review process ==
  
 
* All PRs ''must'' pass all tests for all supported platforms of [[Git Commit Tester|autotester]] before they will be merged
 
* All PRs ''must'' pass all tests for all supported platforms of [[Git Commit Tester|autotester]] before they will be merged
Line 61: Line 118:
 
* Smaller additions like individual functions can be merged directly after [https://github.com/andralex @andralex] approves
 
* Smaller additions like individual functions can be merged directly after [https://github.com/andralex @andralex] approves
 
* Refactoring or bug fixes just need approval (LGTM) from two reviewers and enough time passed (usually 2-3 days, depending on weekends and holidays) to give everyone an opportunity to shout
 
* Refactoring or bug fixes just need approval (LGTM) from two reviewers and enough time passed (usually 2-3 days, depending on weekends and holidays) to give everyone an opportunity to shout
* For low-level changes the other compiler devs (GDC and LLVM) should be consulted
+
* For low-level changes the other compiler developers ([[GDC]] and [[LDC]]) should be consulted
* Trivial changes (e.g. small documentation enhancements) are usually merged in less than 72h - otherwise ping for reviewers
+
* Trivial changes (e.g. small documentation enhancements) are usually merged in less than 24h - otherwise ping for reviewers
 
* If your PR is stalled (no activity for 2-3 days) and you addressed all concerns, don't hesitate to ping your reviewers
 
* If your PR is stalled (no activity for 2-3 days) and you addressed all concerns, don't hesitate to ping your reviewers
* Ping [https://github.com/9il @9il] for anything math related
+
* See [[People#Phobos|here]] for whom to ping
* See [[Starting as a Contributor#rebasing|Rebasing]] if you need to sync your fork with master
+
* See [[Starting as a Contributor#Rebasing|rebasing]] if you need to sync your fork with master
 +
 
 +
== Naming guidelines ==
  
=== Naming ===
+
=== General advice ===
  
 +
* Phobos uses a distinct [[Naming conventions|naming scheme]]
 
* Use a Capitalized short (50 chars or less) Git commit summary
 
* Use a Capitalized short (50 chars or less) Git commit summary
 
* If necessary, wrap your Git explanation paragraph [http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html to 72 chars]
 
* If necessary, wrap your Git explanation paragraph [http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html to 72 chars]
Line 74: Line 134:
 
* Does your PR have a concise and informative title?
 
* Does your PR have a concise and informative title?
 
* Are your Git messages clear and informative (otherwise use <code>git commit --amend</code> for a single commit or <code>git rebase</code> for multiple commits)?
 
* Are your Git messages clear and informative (otherwise use <code>git commit --amend</code> for a single commit or <code>git rebase</code> for multiple commits)?
* Avoid having many commits per PR (usually one commit per PR) - see [[Starting_as_a_Contributor#Someone_asked_me_to_squash_my_commits.2C_what_does_that_mean.3F|squashing]] to combine commits
+
* Ideally, every commit should contain one easily-explained, self-contained change. [[Starting_as_a_Contributor#Someone_asked_me_to_squash_my_commits.2C_what_does_that_mean.3F|Squash]] fix-ups to your previous commits into the commit they target.
  
=== Fixing issues ===
+
=== Issues ===
  
 
* Bug fix PRs should have a separate commit for each bugzilla issue that it fixes
 
* Bug fix PRs should have a separate commit for each bugzilla issue that it fixes
* The message of the commit actually fixes the bug should start with &quot;Fix issue X&quot; where X is the number of the corresponding [https://issues.dlang.org bugzilla] issue. For example:
+
* The message of the commit actually fixes the bug should start with &quot;Fix Bugzulla issue X&quot; where X is the number of the corresponding [https://issues.dlang.org bugzilla] issue. For example:
  
 
<pre>+ Refactor the code assist with the bug fix
 
<pre>+ Refactor the code assist with the bug fix
+ Fix issue 17000 - map doesn't accept some range types
+
+ Fix Bugzulla issue 17000 - map doesn't accept some range types
+ Fix issue 17001 - map doesn't work with some other range type</pre>
+
+ Fix Bugzulla issue 17001 - map doesn't work with some other range type</pre>
 
* Unrelated fixes, refactorings or additions should preferably go separate pull request(s) (tightly related fixes are okay in the same PR)
 
* Unrelated fixes, refactorings or additions should preferably go separate pull request(s) (tightly related fixes are okay in the same PR)
 +
 +
See the [https://github.com/dlang-bots/dlang-bot#automated-references Dlang-Bot explanation] on referencing issues for more details.
  
 
== Documentation ==
 
== Documentation ==
Line 90: Line 152:
 
=== Documentation style ===
 
=== Documentation style ===
  
* The documentation is written in [http://dlang.org/spec/ddoc.html ddoc]
+
* The documentation is written in [https://dlang.org/spec/ddoc.html Ddoc]
 
* Use complete English sentences with correct syntax, grammar, and punctuation
 
* Use complete English sentences with correct syntax, grammar, and punctuation
 
* Use precise technical terms. Avoids colloquialisms
 
* Use precise technical terms. Avoids colloquialisms
Line 102: Line 164:
  
 
* Read your documentation text aloud - is it understandable?
 
* Read your documentation text aloud - is it understandable?
* Check the output of CyberShadows's DAutoTest of the documentation (or run [https://github.com/D-Programming-Language/dlang.org it] yourself)
+
* Check the output of CyberShadows's DAutoTest of the documentation (or run [https://github.com/dlang/dlang.org it] yourself)
* All user impacting changes should have a corresponding [https://github.com/D-Programming-Language/phobos/blob/master/changelog.dd changelog] entry
+
* All user impacting changes should have a corresponding [https://github.com/dlang/phobos/blob/master/changelog.dd changelog] entry
* Did you add your method to the summary booktable or cheatsheat of a module? (might be in <code>package.d</code>)
+
* Did you add your method to the summary booktable or cheat sheet of a module? (might be in <code>package.d</code>)
  
 
=== Documentation tricks ===
 
=== Documentation tricks ===
Line 117: Line 179:
 
* Don't put examples in your ddoc header - use the <code>///</code> magic to annotate them. Ddoc will automatically add the annotated test(s) to the <code>Examples</code> section of the method, e.g.:
 
* Don't put examples in your ddoc header - use the <code>///</code> magic to annotate them. Ddoc will automatically add the annotated test(s) to the <code>Examples</code> section of the method, e.g.:
  
<pre>///
+
<syntaxhighlight lang=D>///
 
unittest
 
unittest
 
{
 
{
 
     assert(1 == 1);
 
     assert(1 == 1);
}</pre>
+
}</syntaxhighlight>
 +
 
 
* Use <code>/// ditto</code> to join multiple methods in the documentation
 
* Use <code>/// ditto</code> to join multiple methods in the documentation
  
Line 129: Line 192:
  
 
Thank you for your contribution!
 
Thank you for your contribution!
 +
 +
== See Also ==
 +
 +
* [[Starting as a Contributor]]
 +
* [[Guidelines for maintainers]]
 +
* [[Get involved]]
 +
 +
[[Category: Contribution Guidelines]]

Latest revision as of 12:53, 9 October 2024

Welcome to the D community and thanks for your interest in contributing! If you need help you can ask questions on #d IRC channel on libera.chat (web interface) or on our forum.

For a lists of ideas on how to contribute, please see Get involved. This document provides advice on making a good pull request to Phobos.

Guidelines for contributing to Phobos

The usual workflow is:

  1. Fork Phobos on GitHub
  2. Create your own branch
  3. Work locally on your new feature or fix (see the tips below)
  4. Test your improvements locally
  5. Submit your pull request (PR)

You can find build instructions here. Below is a list of tips and checks that you should consider before opening your pull request:

Unittest phobos

This section explains commands which are commonly used to test the D standard library phobos.

Full build

If you want to work on phobos itself, you need to run unittests—either for the full library, a package, or a module. To unittest the entire library:

make -j16 -f posix.mak unittest

Adjust the parameter passed to -j depending on your machine (beefier machines support larger parameters). This command unittests phobos in both debug and release mode. To only test one of them, add BUILD=debug or BUILD=release to the command line, for example:

make -j16 -f posix.mak BUILD=debug unittest

Specifying BUILD makes unittesting faster so it is recommended in iterative development. Just make sure both debug and release builds are tested before e.g. submitting a pull request.

Test a single Phobos module

While changing one specific package or module, it's useful to be able to only unittest that particular entity. The following two commands only unittest (in debug mode) the std.algorithm package:

make -j16 -f posix.mak BUILD=debug std/algorithm.test

Several modules, packages, or mix thereof may be specified for testing in the same command line. For example, this command also tests (and also in debug mode) the std.algorithm package and the std.conv module, with better parallelism:

make -j16 -f posix.mak BUILD=debug std/algorithm.test std/conv.test

Test a single module without rebuilding Phobos

You can test a module directly with rdmd:

rdmd --compiler=~/dlang/dmd/generated/linux/release/64/dmd -unittest -main std/algorithm/sorting.d

(If you are on a different platform, replace linux> with your respective platform)

However, be aware that this method doesn't recompile the Phobos library and thus only checks the executed file. Thus you should only use this for fast builds on small changes.

Run CI checks

The auto-tester will fail your PR if your changes contain trailing whitespace or incorrect line endings. You can run this test locally with the command:

make -j16 -f posix.mak checkwhitespace

CircleCi will also run various checks for the DStyle and ensures that every example is runnable on dlang.org. You can run this test locally with:

make -f posix.mak style

Code

Code style

  • Stick to the style guide? (e.g. braces in their own lines (allman style) or white spaces between operators)
  • Avoid unnecessarily importing other Phobos modules
  • Try to not require the garbage collector (this is not a must)
  • Avoid code duplication
  • Avoid using auto as return type wherever possible (makes the documentation easier to read)
  • Use static nested structs for ranges (aka Voldemort types) and thus store function parameters explicitly in the nested struct
  • Avoid unittest in templates (it will generate a new unittest for each instance) - put your tests outside
  • Do overflow checks when computing sizes for malloc and realloc

Code advice

  • Don't be afraid to use the new compiler or language features (e.g. Foo!Range vs. Foo!(Range))
  • Be critical when looking at Phobos code (some parts of Phobos are a bit older and have some relics due to lacking functionality of the compiler)
  • Is there an easier or more performant way to do it?
  • Does your PR address only one topic? Can it be split up in smaller PRs?
  • Is your code flexible enough to accommodate more use cases?
  • Read through your code again - is there any part that is not understandable?

Tests

  • Autotester will automatically compile the code in your PR and test it on all supported platforms. For your first PR you need approval from any reviewer - ping them in case they forget.
  • Do all tests pass locally? You can run the tests of
    • single module or packages with make -f posix.mak std/algorithm/comparison.test or make -f posix.mak std/algorithm.test
    • all tests with make -f posix.mak unittest (add -j NUMBER_OF_CORES if you have multiple cores)
    • for small changes in a single module faster with rdmd -main -unittest comparison.d (be careful, this links to your current Phobos version)
    • for Windows have a look at building Phobos under windows)
  • Do your tests cover all cases? (you can check code coverage in the resulting module.lst of rdmd -cov -main -unittest module.d)
  • Make sure the new code compiles with the -dip1000 switch.

Review process

  • All PRs must pass all tests for all supported platforms of autotester before they will be merged
  • Big additions (new modules) should go to std.experimental first (after they pass the review process)
  • Smaller additions like individual functions can be merged directly after @andralex approves
  • Refactoring or bug fixes just need approval (LGTM) from two reviewers and enough time passed (usually 2-3 days, depending on weekends and holidays) to give everyone an opportunity to shout
  • For low-level changes the other compiler developers (GDC and LDC) should be consulted
  • Trivial changes (e.g. small documentation enhancements) are usually merged in less than 24h - otherwise ping for reviewers
  • If your PR is stalled (no activity for 2-3 days) and you addressed all concerns, don't hesitate to ping your reviewers
  • See here for whom to ping
  • See rebasing if you need to sync your fork with master

Naming guidelines

General advice

  • Phobos uses a distinct naming scheme
  • Use a Capitalized short (50 chars or less) Git commit summary
  • If necessary, wrap your Git explanation paragraph to 72 chars
  • Do you use clear variable names?
  • Does your PR have a concise and informative title?
  • Are your Git messages clear and informative (otherwise use git commit --amend for a single commit or git rebase for multiple commits)?
  • Ideally, every commit should contain one easily-explained, self-contained change. Squash fix-ups to your previous commits into the commit they target.

Issues

  • Bug fix PRs should have a separate commit for each bugzilla issue that it fixes
  • The message of the commit actually fixes the bug should start with "Fix Bugzulla issue X" where X is the number of the corresponding bugzilla issue. For example:
+ Refactor the code assist with the bug fix
+ Fix Bugzulla issue 17000 - map doesn't accept some range types
+ Fix Bugzulla issue 17001 - map doesn't work with some other range type
  • Unrelated fixes, refactorings or additions should preferably go separate pull request(s) (tightly related fixes are okay in the same PR)

See the Dlang-Bot explanation on referencing issues for more details.

Documentation

Documentation style

  • The documentation is written in Ddoc
  • Use complete English sentences with correct syntax, grammar, and punctuation
  • Use precise technical terms. Avoids colloquialisms
  • Honestly describe limitations and dangers
  • Add Params, Returns and if needed See_Also sections
  • Provide at least one ddoced unittest for a new method
  • Have a brief one sentence summary for at the beginning of a method
  • Give a synopsis at the beginning of a module accompanied by an example

Documentation checks

  • Read your documentation text aloud - is it understandable?
  • Check the output of CyberShadows's DAutoTest of the documentation (or run it yourself)
  • All user impacting changes should have a corresponding changelog entry
  • Did you add your method to the summary booktable or cheat sheet of a module? (might be in package.d)

Documentation tricks

  • Use backticks `code` instead of $(D foo)
  • Start with a Capital letter in all blocks of the method header
  • Use $(REF) for links to other methods (format is $(REF _stripLeft, std, algorithm, mutation))
  • Use $(REF_ALTTEXT) for a different link name (format is $(REF_ALTTEXT your text, formattedRead, std, format)
  • Variables will be automatically put in backticks, use an underscore to avoid this behavior (e.g. _foo)
  • Section headings are marked by a line with a single word followed by a colon :, use an underscore to avoid this behavior (e.g. with the following \n code: needs _code to avoid the creation of a section)
  • Section headings with multiple words should use underscores instead of spaces (e.g. See_Also:)
  • Don't put examples in your ddoc header - use the /// magic to annotate them. Ddoc will automatically add the annotated test(s) to the Examples section of the method, e.g.:
///
unittest
{
    assert(1 == 1);
}
  • Use /// ditto to join multiple methods in the documentation

Happy hacking!

If you find a new gotcha, don't hesitate to edit this guide.

Thank you for your contribution!

See Also