- Please use
pylint
andflake8
to check your code for lint. There are config files in the repo. - There is a python
unittest
suite incmakelangtests.py
. Run withpython -Bm cmakelang.tests
(ensure modified code is on the python path). Alternatively you can usecmake
(make test
,ninja test
, etc) or bazel (bazel test ...
). - There's an
autopep8
config file in the repo as well. Feel free to use that to format the code. Note thatautopep8
andpylint
disagree in a few places so usingautopep8
may require some manual edits afterward.
You don't need to "build" cmake-format
, but there are cmake
and
bazel
build rules that you can use if you find it convenient. For the
most part your contribution is in good shape if the test
and lint
(cmake) build targets pass or, equivalently, if bazel test ...
passes.
If you add new files to the repository, please update the corresponding
CMakeLists.txt
and BUILD
files to keep the lint and test configurations
up to date.
Whether or not to write your tests in cmake or in python will depend largely on the test. If you simply want to assert that a particular snippet of code is formatted in a specific way, writing the test in cmake is most natural. If any logic is needed, then writing in the body of a python function makes the most sense.
Test written in cmake are stored in .cmake
sidecar files associated with
python unittest
cases (see command_tests/*
).
The format of these tests are very simple. The test begins with a line comment in the form of:
# test: <test-name>
And ends with the start of the next test, the end of the file, or a line comment in the form of:
# end-test
If non-default configuration options are required, or if you would like to
assert a lex, parse, or layout result, then you can specify that in an optional
bracket comment immediately following the # test:
sentinel. The bracket
comment must begin and end on it's own line, such as:
#[=[ line_width = 10 ]=]
The content of the comment is parsed as python and variables are interpreted as configuration variables, except for the following:
- expect_lex - a list of lexer tokens indicated the expected lex result
- expect_parse - a tree of parse node names indicated the expected parse tree structure
- expect_layout - a tree of layout node names and geometries indicated the expected layout result.
A test called test_<test-name>
will be generated at runtime. The test will
involve cmake-format
formatting the code snippet using the default
configuration, and asserting that the output matches the input.
For the most part, cmake-format ignores white-space when it parses the list
file into the parse tree so most of the formatting tests can
be restricted to "idempotency" tests. In other words, you write down the
listfile code in the format you expect and if cmake-format
doesn't change
it, the test passes.
If you suspect a problem with the lexing, parsing, or layout algorithms,
try to create a minimial working example of the problem, and use the
--dump [lex|parse|layout]
command line option to inspect the output of the
different phases.
Once you've identified the problem, the best thing to do is create a test asserting an expected output at the problematic phase. You can start by asserting an empty output. For example, something like:
# test: debug_my_case
#[=[
expect_lex = []
]=]
if(something)
your_cmake_code_here(foo bar baz)
else()
The test will fail, but the error message will print out the actual result. In the example above:
Second list contains 19 additional elements. First extra element 0: TokenType.WORD - [] + [TokenType.WORD, + TokenType.LEFT_PAREN, + TokenType.WORD, + TokenType.RIGHT_PAREN, + TokenType.NEWLINE, + TokenType.WHITESPACE, + TokenType.WORD, + TokenType.LEFT_PAREN, + TokenType.WORD, + TokenType.WHITESPACE, + TokenType.WORD, + TokenType.WHITESPACE, + TokenType.WORD, + TokenType.RIGHT_PAREN, + TokenType.NEWLINE, + TokenType.WORD, + TokenType.LEFT_PAREN, + TokenType.RIGHT_PAREN, + TokenType.NEWLINE]
You can copy-paste the actual output as the expected output as a starting point for your test. You can modify the "expected" specification to match what the output should be. Then, as you iterate, you can use the test to know when you've fixed the problem.
Feel free to make a pull request on github, though please take note of the following rules and guidelines. These rules are enforced through the travis CI builds so if travis passes your submission is probably in good shape.
Please squash your changes when issuing a pull request so that the request is for a single commit. This helps us move the patch from the public github mirror into the upstream respository. When updating your request, please squash additional commits (you will likely need to force-push to your feature branch).
Please rebase your patch on the current HEAD before submitting the pull request. This helps us to keep a tidy history. When we merge your commit we don't want to create graph connections across long regions of the git history. Travis will fail any pull request which is more than 10 commits behind the HEAD.
When making a pull request, please sign the commit (use git commit -S
).
Please sign the copyright assignment agreement (details below) using the same PGP key you use to sign the commit, and please ensure that the key is available on the popular keyservers. Travis will fetch it from https://keyserver.ubuntu.com
To sign the copyright assignment agreement the quick way, run:
python -Bm cmakelang.contrib.sign_ca
from the root of the repository.
For the long way, please follow this process:
Copy the file
cmakelang/contrib/individual_ca.txt
to some working directory as, e.g.,cmake-format-ca.txt.in
.Replace the template strings at the bottom with your actual name and email address.
Sign the document with e.g.:
gpg --output cmake-format-ca.txt --clearsign cmake-format-ca.txt.in``
Please be sure to use the same pgp key that you'll be using to sign your commits.
Copy the asci-armored signature packet at the bottom of the signed document and paste it into
cmakelang/contrib/signature_db.json
. Include this change in your first pull request.
In general, copyright for contributions should be assigned to the project.
This should keep everything on the level should we find the need to offer
cmake-format
though additional licenses in the future.
If you'd like to make a significant contribution to cmake-format
but don't
agree to the terms of the copyright assignment please contact us to set up an
alternate agreement. Otherwise, please consider filing a feature-request for
changes you would like to see implemented.