summary refs log tree commit diff stats
path: root/doc/contributing.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/contributing.rst')
-rw-r--r--doc/contributing.rst557
1 files changed, 0 insertions, 557 deletions
diff --git a/doc/contributing.rst b/doc/contributing.rst
deleted file mode 100644
index a4baaef05..000000000
--- a/doc/contributing.rst
+++ /dev/null
@@ -1,557 +0,0 @@
-============
-Contributing
-============
-
-.. contents::
-
-
-Contributing happens via "Pull requests" (PR) on github. Every PR needs to be
-reviewed before it can be merged and the Continuous Integration should be green.
-
-The PR has to be approved (and is often merged too) by one "code owner", either
-by the code owner who is responsible for the subsystem the PR belongs to or by
-two core developers or by Araq.
-
-See `codeowners <codeowners.html>`_ for more details.
-
-
-Writing tests
-=============
-
-There are 4 types of tests:
-
-1. ``runnableExamples`` documentation comment tests, ran by ``nim doc mymod.nim``
-   These end up in documentation and ensure documentation stays in sync with code.
-
-2. separate test files, e.g.: ``tests/stdlib/tos.nim``.
-   In nim repo, `testament` (see below) runs all `$nim/tests/*/t*.nim` test files;
-   for nimble packages, see https://github.com/nim-lang/nimble#tests.
-
-3. (deprecated) tests in ``when isMainModule:`` block, ran by ``nim r mymod.nim``.
-   ``nimble test`` can run those in nimble packages when specified in a
-   `task "test"`.
-
-4. (not preferred) `.. code-block:: nim` RST snippets; these should only be used in rst sources,
-   in nim sources `runnableExamples` should now always be preferred to those for
-   several reasons (cleaner syntax, syntax highlights, batched testing, and
-   `rdoccmd` allows customization).
-
-Not all the tests follow the convention here, feel free to change the ones
-that don't. Always leave the code cleaner than you found it.
-
-Stdlib
-------
-
-Each stdlib module (anything under ``lib/``, e.g. ``lib/pure/os.nim``) should
-preferably have a corresponding separate test file, eg `tests/stdlib/tos.nim`.
-The old convention was to add a ``when isMainModule:`` block in the source file,
-which only gets executed when the tester is building the file.
-
-Each test should be in a separate ``block:`` statement, such that
-each has its own scope. Use boolean conditions and ``doAssert`` for the
-testing by itself, don't rely on echo statements or similar; in particular avoid
-things like `echo "done"`.
-
-Sample test:
-
-.. code-block:: nim
-
-  block: # bug #1234
-    static: doAssert 1+1 == 2
-
-  block: # bug #1235
-    var seq2D = newSeqWith(4, newSeq[bool](2))
-    seq2D[0][0] = true
-    seq2D[1][0] = true
-    seq2D[0][1] = true
-    doAssert seq2D == @[@[true, true], @[true, false],
-                        @[false, false], @[false, false]]
-    # doAssert with `not` can now be done as follows:
-    doAssert not (1 == 2)
-
-Always refer to a github issue using the following exact syntax: `bug #1234` as shown
-above, so that it's consistent and easier to search or for tooling. Some browser
-extensions (eg https://github.com/sindresorhus/refined-github) will even turn those
-in clickable links when it works.
-
-Rationale for using a separate test file instead of `when isMainModule:` block:
-* allows custom compiler flags or testing options (see details below)
-* faster CI since they can be joined in `megatest` (combined into a single test)
-* avoids making the parser do un-necessary work when a source file is merely imported
-* avoids mixing source and test code when reporting line of code statistics or code coverage
-
-Compiler
---------
-
-The tests for the compiler use a testing tool called ``testament``. They are all
-located in ``tests/`` (e.g.: ``tests/destructor/tdestructor3.nim``).
-Each test has its own file. All test files are prefixed with ``t``. If you want
-to create a file for import into another test only, use the prefix ``m``.
-
-At the beginning of every test is the expected behavior of the test.
-Possible keys are:
-
-- ``cmd``: A compilation command template e.g. ``nim $target --threads:on $options $file``
-- ``output``: The expected output (stdout + stderr), most likely via ``echo``
-- ``exitcode``: Exit code of the test (via ``exit(number)``)
-- ``errormsg``: The expected compiler error message
-- ``file``: The file the errormsg was produced at
-- ``line``: The line the errormsg was produced at
-
-For a full spec, see here: ``testament/specs.nim``
-
-An example for a test:
-
-.. code-block:: nim
-
-  discard """
-    errormsg: "type mismatch: got (PTest)"
-  """
-
-  type
-    PTest = ref object
-
-  proc test(x: PTest, y: int) = nil
-
-  var buf: PTest
-  buf.test()
-
-
-Running tests
-=============
-
-You can run the tests with
-
-::
-
-  ./koch tests
-
-which will run a good subset of tests. Some tests may fail. If you
-only want to see the output of failing tests, go for
-
-::
-
-  ./koch tests --failing all
-
-You can also run only a single category of tests. A category is a subdirectory
-in the ``tests`` directory. There are a couple of special categories; for a
-list of these, see ``testament/categories.nim``, at the bottom.
-
-::
-
-  ./koch tests c lib # compiles/runs stdlib modules, including `isMainModule` tests
-  ./koch tests c megatest # runs a set of tests that can be combined into 1
-
-To run a single test:
-
-::
-
-  ./koch test run <category>/<name>    # e.g.: tuples/ttuples_issues
-  ./koch test run tests/stdlib/tos.nim # can also provide relative path
-
-For reproducible tests (to reproduce an environment more similar to the one
-run by Continuous Integration on travis/appveyor), you may want to disable your
-local configuration (e.g. in ``~/.config/nim/nim.cfg``) which may affect some
-tests; this can also be achieved by using
-``export XDG_CONFIG_HOME=pathtoAlternateConfig`` before running ``./koch``
-commands.
-
-
-Comparing tests
-===============
-
-Test failures can be grepped using ``Failure:``.
-
-The tester can compare two test runs. First, you need to create the
-reference test. You'll also need to the commit id, because that's what
-the tester needs to know in order to compare the two.
-
-::
-
-  git checkout devel
-  DEVEL_COMMIT=$(git rev-parse HEAD)
-  ./koch tests
-
-Then switch over to your changes and run the tester again.
-
-::
-
-  git checkout your-changes
-  ./koch tests
-
-Then you can ask the tester to create a ``testresults.html`` which will
-tell you if any new tests passed/failed.
-
-::
-
-  ./koch tests --print html $DEVEL_COMMIT
-
-
-Deprecation
-===========
-
-Backward compatibility is important, so instead of a rename you need to deprecate
-the old name and introduce a new name:
-
-.. code-block:: nim
-
-  # for routines (proc/template/macro/iterator) and types:
-  proc oldProc(a: int, b: float): bool {.deprecated:
-      "deprecated since v1.2.3; use `newImpl: string -> int` instead".} = discard
-
-  # for (const/var/let/fields) the msg is not yet supported:
-  const Foo {.deprecated.}  = 1
-
-  # for enum types, you can deprecate the type or some elements
-  # (likewise with object types and their fields):
-  type Bar {.deprecated.} = enum bar0, bar1
-  type Barz  = enum baz0, baz1 {.deprecated.}, baz2
-
-
-See also `Deprecated <manual.html#pragmas-deprecated-pragma>`_
-pragma in the manual.
-
-
-Documentation
-=============
-
-When contributing new procs, be sure to add documentation, especially if
-the proc is public. Even private procs benefit from documentation and can be
-viewed using ``nim doc --docInternal foo.nim``.
-Documentation begins on the line
-following the ``proc`` definition, and is prefixed by ``##`` on each line.
-
-Runnable code examples are also encouraged, to show typical behavior with a few
-test cases (typically 1 to 3 ``assert`` statements, depending on complexity).
-These ``runnableExamples`` are automatically run by ``nim doc mymodule.nim``
-as well as ``testament`` and guarantee they stay in sync.
-
-.. code-block:: nim
-  proc addBar*(a: string): string =
-    ## Adds "Bar" to `a`.
-    runnableExamples:
-      assert "baz".addBar == "bazBar"
-    result = a & "Bar"
-
-See `parentDir <os.html#parentDir,string>`_ example.
-
-The RestructuredText Nim uses has a special syntax for including code snippets
-embedded in documentation; these are not run by ``nim doc`` and therefore are
-not guaranteed to stay in sync, so ``runnableExamples`` is usually preferred:
-
-.. code-block:: nim
-
-  proc someproc*(): string =
-    ## Return "something"
-    ##
-    ## .. code-block::
-    ##  echo someproc() # "something"
-    result = "something" # single-hash comments do not produce documentation
-
-The ``.. code-block:: nim`` followed by a newline and an indentation instructs the
-``nim doc`` command to produce syntax-highlighted example code with the
-documentation (``.. code-block::`` is sufficient from inside a nim module).
-
-When forward declaration is used, the documentation should be included with the
-first appearance of the proc.
-
-.. code-block:: nim
-
-  proc hello*(): string
-    ## Put documentation here
-  proc nothing() = discard
-  proc hello*(): string =
-    ## ignore this
-    echo "hello"
-
-The preferred documentation style is to begin with a capital letter and use
-the imperative (command) form. That is, between:
-
-.. code-block:: nim
-
-  proc hello*(): string =
-    ## Return "hello"
-    result = "hello"
-
-or
-
-.. code-block:: nim
-
-  proc hello*(): string =
-    ## says hello
-    result = "hello"
-
-the first is preferred.
-
-
-Best practices
-==============
-
-Note: these are general guidelines, not hard rules; there are always exceptions.
-Code reviews can just point to a specific section here to save time and
-propagate best practices.
-
-.. _define_needs_prefix:
-New `defined(foo)` symbols need to be prefixed by the nimble package name, or
-by `nim` for symbols in nim sources (e.g. compiler, standard library). This is
-to avoid name conflicts across packages.
-
-.. code-block:: nim
-
-  # if in nim sources
-  when defined(allocStats): discard # bad, can cause conflicts
-  when defined(nimAllocStats): discard # preferred
-  # if in a pacakge `cligen`:
-  when defined(debug): discard # bad, can cause conflicts
-  when defined(cligenDebug): discard # preferred
-
-.. _noimplicitbool:
-Take advantage of no implicit bool conversion
-
-.. code-block:: nim
-
-  doAssert isValid() == true
-  doAssert isValid() # preferred
-
-.. _design_for_mcs:
-Design with method call syntax chaining in mind
-
-.. code-block:: nim
-
-  proc foo(cond: bool, lines: seq[string]) # bad
-  proc foo(lines: seq[string], cond: bool) # preferred
-  # can be called as: `getLines().foo(false)`
-
-.. _avoid_quit:
-Use exceptions (including assert / doAssert) instead of ``quit``
-rationale: https://forum.nim-lang.org/t/4089
-
-.. code-block:: nim
-
-  quit() # bad in almost all cases
-  doAssert() # preferred
-
-.. _tests_use_doAssert:
-Use ``doAssert`` (or ``require``, etc), not ``assert`` in all tests so they'll
-be enabled even in release mode (except for tests in ``runnableExamples`` blocks
-which for which ``nim doc`` ignores ``-d:release``).
-
-.. code-block:: nim
-
-  when isMainModule:
-    assert foo() # bad
-    doAssert foo() # preferred
-
-.. _delegate_printing:
-Delegate printing to caller: return ``string`` instead of calling ``echo``
-rationale: it's more flexible (e.g. allows caller to call custom printing,
-including prepending location info, writing to log files, etc).
-
-.. code-block:: nim
-
-  proc foo() = echo "bar" # bad
-  proc foo(): string = "bar" # preferred (usually)
-
-.. _use_Option:
-[Ongoing debate] Consider using Option instead of return bool + var argument,
-unless stack allocation is needed (e.g. for efficiency).
-
-.. code-block:: nim
-
-  proc foo(a: var Bar): bool
-  proc foo(): Option[Bar]
-
-.. _use_doAssert_not_echo:
-Tests (including in testament) should always prefer assertions over ``echo``,
-except when that's not possible. It's more precise, easier for readers and
-maintaners to where expected values refer to. See for example
-https://github.com/nim-lang/Nim/pull/9335 and https://forum.nim-lang.org/t/4089
-
-.. code-block:: nim
-
-  echo foo() # adds a line for testament in `output:` block inside `discard`.
-  doAssert foo() == [1, 2] # preferred, except when not possible to do so.
-
-
-The Git stuff
-=============
-
-General commit rules
---------------------
-
-1. Important, critical bugfixes that have a tiny chance of breaking
-   somebody's code should be backported to the latest stable release
-   branch (currently 1.2.x) and maybe also to the 1.0 branch.
-   The commit message should contain the tag ``[backport]`` for "backport to all
-   stable releases" and the tag ``[backport:$VERSION]`` for backporting to the
-   given $VERSION.
-
-2. If you introduce changes which affect backwards compatibility,
-   make breaking changes, or have PR which is tagged as ``[feature]``,
-   the changes should be mentioned in `the changelog
-   <https://github.com/nim-lang/Nim/blob/devel/changelog.md>`_.
-
-3. All changes introduced by the commit (diff lines) must be related to the
-   subject of the commit.
-
-   If you change something unrelated to the subject parts of the file, because
-   your editor reformatted automatically the code or whatever different reason,
-   this should be excluded from the commit.
-
-   *Tip:* Never commit everything as is using ``git commit -a``, but review
-   carefully your changes with ``git add -p``.
-
-4. Changes should not introduce any trailing whitespace.
-
-   Always check your changes for whitespace errors using ``git diff --check``
-   or add following ``pre-commit`` hook:
-
-   .. code-block:: sh
-
-      #!/bin/sh
-      git diff --check --cached || exit $?
-
-5. Describe your commit and use your common sense.
-   Example commit message:
-
-   ``Fixes #123; refs #124``
-
-   indicates that issue ``#123`` is completely fixed (github may automatically
-   close it when the PR is committed), wheres issue ``#124`` is referenced
-   (e.g.: partially fixed) and won't close the issue when committed.
-
-6. Commits should be always be rebased against devel (so a fast forward
-   merge can happen)
-
-   e.g.: use ``git pull --rebase origin devel``. This is to avoid messing up
-   git history.
-   Exceptions should be very rare: when rebase gives too many conflicts, simply
-   squash all commits using the script shown in
-   https://github.com/nim-lang/Nim/pull/9356
-
-7. Do not mix pure formatting changes (e.g. whitespace changes, nimpretty) or
-   automated changes (e.g. nimfix) with other code changes: these should be in
-   separate commits (and the merge on github should not squash these into 1).
-
-
-Continuous Integration (CI)
----------------------------
-
-1. Continuous Integration is by default run on every push in a PR; this clogs
-   the CI pipeline and affects other PR's; if you don't need it (e.g. for WIP or
-   documentation only changes), add ``[ci skip]`` to your commit message title.
-   This convention is supported by `Appveyor
-   <https://www.appveyor.com/docs/how-to/filtering-commits/#skip-directive-in-commit-message>`_
-   and `Travis <https://docs.travis-ci.com/user/customizing-the-build/#skipping-a-build>`_.
-
-2. Consider enabling CI (travis and appveyor) in your own Nim fork, and
-   waiting for CI to be green in that fork (fixing bugs as needed) before
-   opening your PR in original Nim repo, so as to reduce CI congestion. Same
-   applies for updates on a PR: you can test commits on a separate private
-   branch before updating the main PR.
-
-Code reviews
-------------
-
-1. Whenever possible, use github's new 'Suggested change' in code reviews, which
-   saves time explaining the change or applying it; see also
-   https://forum.nim-lang.org/t/4317
-
-2. When reviewing large diffs that may involve code moving around, github's interface
-   doesn't help much as it doesn't highlight moves. Instead you can use something
-   like this, see visual results `here <https://github.com/nim-lang/Nim/pull/10431#issuecomment-456968196>`_:
-
-   .. code-block:: sh
-
-      git fetch origin pull/10431/head && git checkout FETCH_HEAD
-      git diff --color-moved-ws=allow-indentation-change --color-moved=blocks HEAD^
-
-3. In addition, you can view github-like diffs locally to identify what was changed
-   within a code block using `diff-highlight` or `diff-so-fancy`, e.g.:
-
-   .. code-block:: sh
-
-      # put this in ~/.gitconfig:
-      [core]
-        pager = "diff-so-fancy | less -R" # or: use: `diff-highlight`
-
-
-
-.. include:: docstyle.rst
-
-
-Evolving the stdlib
-===================
-
-As outlined in https://github.com/nim-lang/RFCs/issues/173 there are a couple
-of guidelines about what should go into the stdlib, what should be added and
-what eventually should be removed.
-
-
-What the compiler itself needs must be part of the stdlib
----------------------------------------------------------
-
-Maybe in the future the compiler itself can depend on Nimble packages but for
-the time being, we strive to have zero dependencies in the compiler as the
-compiler is the root of the bootstrapping process and is also used to build
-Nimble.
-
-
-Vocabulary types must be part of the stdlib
--------------------------------------------
-
-These are types most packages need to agree on for better interoperability,
-for example ``Option[T]``. This rule also covers the existing collections like
-``Table``, ``CountTable`` etc. "Sorted" containers based on a tree-like data
-structure are still missing and should be added.
-
-Time handling, especially the ``Time`` type are also covered by this rule.
-
-
-Existing, battle-tested modules stay
-------------------------------------
-
-Reason: There is no benefit in moving them around just to fullfill some design
-fashion as in "Nim's core MUST BE SMALL". If you don't like an existing module,
-don't import it. If a compilation target (e.g. JS) cannot support a module,
-document this limitation.
-
-This covers modules like ``os``, ``osproc``, ``strscans``, ``strutils``,
-``strformat``, etc.
-
-
-Syntactic helpers can start as experimental stdlib modules
-----------------------------------------------------------
-
-Reason: Generally speaking as external dependencies they are not exposed
-to enough users so that we can see if the shortcuts provide enough benefit
-or not. Many programmers avoid external dependencies, even moreso for
-"tiny syntactic improvements". However, this is only true for really good
-syntactic improvements that have the potential to clean up other parts of
-the Nim library substantially. If in doubt, new stdlib modules should start
-as external, successful Nimble packages.
-
-
-
-Other new stdlib modules do not start as stdlib modules
--------------------------------------------------------
-
-As we strive for higher quality everywhere, it's easier to adopt existing,
-battle-tested modules eventually rather than creating modules from scratch.
-
-
-Little additions are acceptable
--------------------------------
-
-As long as they are documented and tested well, adding little helpers
-to existing modules is acceptable. For two reasons:
-
-1. It makes Nim easier to learn and use in the long run.
-   ("Why does sequtils lack a ``countIt``?
-   Because version 1.0 happens to have lacked it? Silly...")
-2. To encourage contributions. Contributors often start with PRs that
-   add simple things and then they stay and also fix bugs. Nim is an
-   open source project and lives from people's contributions and involvement.
-   Newly introduced issues have to be balanced against motivating new people. We know where
-   to find perfectly designed pieces of software that have no bugs -- these are the systems
-   that nobody uses.