]> git.madduck.net Git - etc/vim.git/blob - .vim/bundle/ale/doc/ale-development.txt

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Do not set EDITOR/VISUAL for shell
[etc/vim.git] / .vim / bundle / ale / doc / ale-development.txt
1 *ale-development.txt*  For Vim version 8.0.
2 *ale-dev*
3 *ale-development*
4
5 ALE Development Documentation
6
7 ===============================================================================
8 CONTENTS                                             *ale-development-contents*
9
10   1. Introduction.........................|ale-development-introduction|
11   2. Design Goals.........................|ale-design-goals|
12   3. Coding Standards.....................|ale-coding-standards|
13   4. Testing ALE..........................|ale-development-tests|
14     4.1. Writing Linter Tests.............|ale-development-linter-tests|
15     4.2. Writing Fixer Tests..............|ale-development-fixer-tests|
16     4.3. Running Tests in a Windows VM....|ale-development-windows-tests|
17   5. Contributing.........................|ale-development-contributing|
18     5.1. Preparing a Release..............|ale-development-release|
19
20
21 ===============================================================================
22 1. Introduction                                  *ale-development-introduction*
23
24 This document contains helpful information for ALE developers, including
25 design goals, information on how to run the tests, coding standards, and so
26 on. You should read this document if you want to get involved with ALE
27 development.
28
29
30 ===============================================================================
31 2. Design Goals                                              *ale-design-goals*
32
33 This section lists design goals for ALE, in no particular order. They are as
34 follows.
35
36 ALE code should be almost 100% VimL. This makes the plugin as portable as
37 possible.
38
39 ALE should run without needing any other plugins to be installed, to make
40 installation simple. ALE can integrate with other plugins for more advanced
41 functionality, non-essential functionality, or improving on basic first party
42 functionality.
43
44 ALE should check files with as many tools as possible by default, except where
45 they cause security issues or make excessive use of resources on modern
46 machines.
47
48 ALE should be free of breaking changes to the public API, which is comprised of
49 documented functions and options, until a major version is planned. Breaking
50 changes should be preceded by a deprecation phase complete with warnings.
51 Changes required for security may be an exception.
52
53 ALE supports Vim 8 and above, and Neovim 0.7.0 or newer. These are the
54 earliest versions of Vim and Neovim which support |+job|, |+timer|,
55 |+closure|, and |+lambda| features. All ALE code should be written so it is
56 compatible with these versions of Vim, or with version checks so particular
57 features can degrade or fail gracefully.
58
59 Just about everything should be documented and covered with tests.
60
61 By and large, people shouldn't pay for the functionality they don't use. Care
62 should be taken when adding new features, so supporting new features doesn't
63 degrade the general performance of anything ALE does.
64
65 LSP support will become more important as time goes on. ALE should provide
66 better support for LSP features as time goes on.
67
68 When merging pull requests, you should respond with `Cheers! :beers:`, purely
69 for comedy value.
70
71
72 ===============================================================================
73 3. Coding Standards                                      *ale-coding-standards*
74
75 The following general coding standards should be adhered to for Vim code.
76
77 * Check your Vim code with `Vint` and do everything it says. ALE will check
78   your Vim code with Vint automatically. See: https://github.com/Kuniwak/vint
79   Read ALE's `Dockerfile` to see which version of `Vint` it uses.
80 * Try to write descriptive and concise names for variables and functions.
81   Names shouldn't be too short or too long. Think about others reading your
82   code later on.
83 * Use `snake_case` names for variables and arguments, and `PascalCase` names
84   for functions. Prefix every variable name with its scope. (`l:`, `g:`, etc.)
85 * Try to keep lines no longer than 80 characters, but this isn't an absolute
86   requirement.
87 * Use 4 spaces for every level of indentation in Vim code.
88 * Add a blank line before every `function`, `if`, `for`, `while`, or `return`,
89   which doesn't start a new level of indentation. This makes the logic in
90   your code easier to follow.
91 * End every file with a trailing newline character, but not with extra blank
92   lines. Remove trailing whitespace from the ends of lines.
93 * Write the full names of commands instead of abbreviations. For example, write
94   `function` instead of `func`, and `endif` instead of `end`.
95 * Write functions with `!`, so files can be reloaded. Use the |abort| keyword
96   for all functions, so functions exit on the first error.
97 * Make sure to credit yourself in files you have authored with `Author:`
98   and `Description:` comments.
99
100 In addition to the above general guidelines for the style of your code, you
101 should also follow some additional rules designed to prevent mistakes. Some of
102 these are reported with ALE's `custom-linting-rules` script. See
103 |ale-development-tests|.
104
105 * Don't leave stray `:echo` lines in code. Write `" no-custom-checks` above
106   the line if you must echo something.
107 * For strings use |is#| instead of |==#|, `is?` instead of `==?`, `isnot#`
108   instead of `!=#`, and `isnot?` instead of `!=?`. This is because `'x' ==# 0`
109   returns 1, while `'x' is# 0` returns 0, so you will experience fewer issues
110   when numbers are compared with strings. `is` and `isnot` also do not throw
111   errors when other objects like List or Dictionaries are compared with
112   strings.
113 * Don't use the `getcwd()` function in the ALE codebase. Most of ALE's code
114   runs from asynchronous callback functions, and these functions can execute
115   from essentially random buffers. Therefore, the `getcwd()` output is
116   useless. Use `expand('#' . a:buffer . ':p:h')` instead. Don't use
117   `expand('%...')` for the same reason.
118 * Don't use the `simplify()` function. It doesn't simplify paths enough. Use
119   `ale#path#Simplify()` instead.
120 * Don't use the `shellescape()` function. It doesn't escape arguments properly
121   on Windows. Use `ale#Escape()` instead, which will avoid escaping where it
122   isn't needed, and generally escape arguments better on Windows.
123 * Don't use the `tempname()` function. It doesn't work when `$TMPDIR` isn't
124   set. Use `ale#util#Tempname()` instead, which temporarily sets `$TMPDIR`
125   appropriately where needed.
126 * Use `snake_case` names for linter names, so they can be used as part of
127   variable names. You can define `aliases` for linters, for other names people
128   might try to configure linters with.
129 * Use |v:t_TYPE| variables instead of `type()`, which are more readable.
130
131 Apply the following guidelines when writing Vader test files.
132
133 * Use 2 spaces for Vader test files, instead of the 4 spaces for Vim files.
134 * If you write `Before` and `After` blocks, you should typically write them at
135   the top of the file, so they run for all tests. There may be some tests
136   where it make sense to modify the `Before` and `After` code part of the way
137   through the file.
138 * If you modify any settings or global variables, reset them in `After`
139   blocks. The Vader `Save` and `Restore` commands can be useful for this
140   purpose.
141 * If you load or define linters in tests, write `call ale#linter#Reset()` in
142   an `After` block.
143 * Just write `Execute` blocks for Vader tests, and don't bother writing `Then`
144   blocks. `Then` blocks execute after `After` blocks in older versions, and
145   that can be confusing.
146
147 Apply the following rules when writing Bash scripts.
148
149 * Run `shellcheck`, and do everything it says.
150   See: https://github.com/koalaman/shellcheck
151 * Try to write scripts so they will run on Linux, BSD, or Mac OSX.
152
153
154 ===============================================================================
155 4. Testing ALE              *ale-development-tests* *ale-dev-tests* *ale-tests*
156
157 ALE is tested with a suite of tests executed via GitHub Actions and AppVeyor.
158 ALE runs tests with the following versions of Vim in the following
159 environments.
160
161 1. Vim 8.0.0027 on Linux via GitHub Actions.
162 2. Vim 9.0.0297 on Linux via GitHub Actions.
163 3. Neovim 0.7.0 on Linux via GitHub Actions.
164 4. Neovim 0.8.0 on Linux via GitHub Actions.
165 6. Vim 8 (stable builds) on Windows via AppVeyor.
166
167 If you are developing ALE code on Linux, Mac OSX, or BSD, you can run ALEs
168 tests by installing Docker and running the `run-tests` script. Follow the
169 instructions on the Docker site for installing Docker.
170 See: https://docs.docker.com/install/
171
172 NOTE: Don't forget to add your user to the `docker` group on Linux, or Docker
173 just won't work. See: https://docs.docker.com/install/linux/linux-postinstall/
174
175 If you run simply `./run-tests` from the ALE repository root directory, the
176 latest Docker image for tests will be downloaded if needed, and the script
177 will run all of the tests in Vader, Vint checks, and several Bash scripts for
178 finding extra issues. Run `./run-tests --help` to see all of the options the
179 script supports. Note that the script supports selecting particular test files.
180
181 Once you get used to dealing with Vim and NeoVim compatibility issues, you
182 probably want to use `./run-tests --fast -q` for running tests with only the
183 fastest available Vim version, and with success messages from tests
184 suppressed.
185
186 Generally write tests for any changes you make. The following types of tests
187 are recommended for the following types of code.
188
189 * New/edited error handler callbacks -> Write tests in `test/handler`
190 * New/edited linter definition       -> Write tests in `test/linter`
191 * New/edited fixer functions         -> Write tests in `test/fixers`
192
193 Look at existing tests in the codebase for examples of how to write tests.
194 Refer to the Vader documentation for general information on how to write Vader
195 tests: https://github.com/junegunn/vader.vim
196
197 If you need to add any supporting files for tests, such as empty files present
198 to test searching upwards through paths for configuration files, they can be
199 added to the `test/test-files` directory.
200
201 See |ale-development-linter-tests| for more information on how to write linter
202 tests.
203
204 When you add new linters or fixers, make sure to add them into the tables in
205 supported-tools.md and |ale-supported-languages-and-tools.txt|. If you forget to
206 keep them both in sync, you should see an error like the following in the
207 builds run for GitHub Actions.
208 >
209   ========================================
210   diff supported-tools.md and doc/ale-supported-languages-and-tools.txt tables
211   ========================================
212   Differences follow:
213
214   --- /tmp/readme.qLjNhJdB        2018-07-01 16:29:55.590331972 +0100
215   +++ /tmp/doc.dAi8zfVE   2018-07-01 16:29:55.582331877 +0100
216   @@ -1 +1 @@
217   - ASM: gcc, foobar
218   + ASM: gcc
219 <
220 Make sure to list documentation entries for linters and fixers in individual
221 help files in the table of contents, and to align help tags to the right
222 margin. For example, if you add a heading for an `aardvark` tool to
223 `ale-python.txt` with a badly aligned doc tag, you will see errors like so. >
224
225   ========================================
226   Look for badly aligned doc tags
227   ========================================
228   Badly aligned tags follow:
229
230   doc/ale-python.txt:aardvark ...
231   ========================================
232   Look for table of contents issues
233   ========================================
234
235   Check for bad ToC sorting:
236
237   Check for mismatched ToC and headings:
238
239   --- /tmp/table-of-contents.mwCFOgSI     2018-07-01 16:33:25.068811878 +0100
240   +++ /tmp/headings.L4WU0hsO      2018-07-01 16:33:25.076811973 +0100
241   @@ -168,6 +168,7 @@
242    pyrex (cython), ale-pyrex-options
243      cython, ale-pyrex-cython
244    python, ale-python-options
245   +  aardvark, ale-python-aardvark
246      autopep8, ale-python-autopep8
247      black, ale-python-black
248      flake8, ale-python-flake8
249 <
250 Make sure to make the table of contents match the headings, and to keep the
251 doc tags on the right margin.
252
253
254 ===============================================================================
255 4.1 Writing Linter Tests                         *ale-development-linter-tests*
256
257 Tests for ALE linters take two forms.
258
259 1. Tests for handling the output of commands.
260 2. Tests for checking which commands are run, or connections are made.
261
262 Tests of the first form should go in the `test/handler` directory, and should
263 be written like so. >
264
265   Before:
266     " Load the file which defines the linter.
267     runtime ale_linters/filetype/linter_name_here.vim
268
269   After:
270     " Unload all linters again.
271     call ale#linter#Reset()
272
273   Execute(The output should be correct):
274
275   " Test that the right loclist items are parsed from the handler.
276   AssertEqual
277   \ [
278   \   {
279   \     'lnum': 1,
280   \     'type': 'E',
281   \     'text': 'Something went wrong',
282   \   },
283   \ ],
284   \ ale_linters#filetype#linter_name#Handle(bufnr(''), [
285   \ '1:Something went wrong',
286   \ ]
287 <
288 Tests for what ALE runs should go in the `test/linter` directory, and should
289 be written like so. >
290
291   Before:
292     " Load the linter and set up a series of commands, reset linter variables,
293     " clear caches, etc.
294     "
295     " Vader's 'Save' command will be called here for linter variables.
296     call ale#assert#SetUpLinterTest('filetype', 'linter_name')
297
298   After:
299     " Reset linters, variables, etc.
300     "
301     " Vader's 'Restore' command will be called here.
302     call ale#assert#TearDownLinterTest()
303
304   Execute(The default command should be correct):
305     " AssertLinter checks the executable and command.
306     " Pass expected_executable, expected_command
307     AssertLinter 'some-command', ale#Escape('some-command') . ' --foo'
308
309   Execute(Check chained commands):
310     " GivenCommandOutput can be called with 1 or more list for passing output
311     " to chained commands. The output for each callback defaults to an empty
312     " list.
313     GivenCommandOutput ['v2.1.2']
314     " Given a List of commands, check all of them.
315     " Given a String, only the last command in the chain will be checked.
316     AssertLinter 'some-command', [
317     \ ale#Escape('some-command') . ' --version',
318     \ ale#Escape('some-command') . ' --foo',
319     \]
320 <
321 The full list of commands that will be temporarily defined for linter tests
322 given the above setup are as follows.
323
324 `GivenCommandOutput [...]`         - Define output for ale#command#Run.
325 `AssertLinterCwd cwd`              - Check the `cwd` for the linter.
326 `AssertLinter executable, command` - Check the executable and command.
327 `AssertLinterNotExecuted`          - Check that linters will not be executed.
328 `AssertLSPLanguage language`       - Check the language given to an LSP server.
329 `AssertLSPOptions options_dict`    - Check the options given to an LSP server.
330 `AssertLSPConfig config_dict`      - Check the config given to an LSP server.
331 `AssertLSPProject project_root`    - Check the root given to an LSP server.
332 `AssertLSPAddress address`         - Check the address to an LSP server.
333
334
335 ===============================================================================
336 4.2 Writing Fixer Tests                           *ale-development-fixer-tests*
337
338 Tests for ALE fixers should go in the `test/fixers` directory, and should
339 be written like so. >
340
341   Before:
342     " Load the fixer and set up a series of commands, reset fixer variables,
343     " clear caches, etc.
344     "
345     " Vader's 'Save' command will be called here for fixer variables.
346     call ale#assert#SetUpFixerTest('filetype', 'fixer_name')
347
348   After:
349     " Reset fixers, variables, etc.
350     "
351     " Vader's 'Restore' command will be called here.
352     call ale#assert#TearDownFixerTest()
353
354   Execute(The default command should be correct):
355     " AssertFixer checks the result of the loaded fixer function.
356     AssertFixer {'command': ale#Escape('some-command') . ' --foo'}
357
358   Execute(Check chained commands):
359     " Same as above for linter tests.
360     GivenCommandOutput ['v2.1.2']
361     " Given a List of commands, check all of them.
362     " Given anything else, only the last result will be checked.
363     AssertFixer [
364     \ ale#Escape('some-command') . ' --version',
365     \ {'command': ale#Escape('some-command') . ' --foo'}
366     \]
367 <
368 The full list of commands that will be temporarily defined for fixer tests
369 given the above setup are as follows.
370
371 `GivenCommandOutput [...]`         - Define output for ale#command#Run.
372 `AssertFixerCwd cwd`               - Check the `cwd` for the fixer.
373 `AssertFixer results`              - Check the fixer results
374 `AssertFixerNotExecuted`           - Check that fixers will not be executed.
375
376
377 ===============================================================================
378 4.3 Running Tests in a Windows VM               *ale-development-windows-tests*
379
380 Tests are run for ALE in a build of Vim 8 for Windows via AppVeyor. These
381 tests can frequently break due to minor differences in paths and how escaping
382 is done for commands on Windows. If you are a Linux or Mac user, running these
383 tests locally can be difficult. Here is a process that will make that easier.
384
385 First, you want to install a Windows image with VirtualBox. Install VirtualBox
386 and grab a VirtualBox image for Windows such as from here:
387 https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/
388
389 NOTE: If you need to enter a password for the virtual machine at any point,
390 the password is "Passw0rd!" without the double quotes.
391
392 NOTE: If your trial period for Windows runs out, run the commands like the
393 wallpaper tells you to.
394
395 Your virtual machine will need to have PowerShell installed. Before you go any
396 further, confirm that PowerShell is installed in your Windows virtual machine.
397
398 Consult the VirtualBox documentation on how to install "Guest Additions."
399 You probably want to install "Guest Additions" for most things to work
400 properly.
401
402 After you've loaded your virtual machine image, go into "Settings" for your
403 virtual machine, and "Shared Folders." Add a shared folder with the name
404 "ale", and set the "Folder Path" to the path to your ALE repository, for
405 example: "/home/w0rp/ale"
406
407 Find out which drive letter "ale" has been mounted as in Windows. We'll use
408 "E:" as the drive letter, for example. Open the command prompt as an
409 administrator by typing in `cmd` in the start menu, right clicking on the
410 command prompt application, and clicking "Run as administrator." Click "Yes"
411 when prompted to ask if you're sure you want to run the command prompt. You
412 should type in the following command to mount the "ale" directory for testing,
413 where "E:" is replaced with your drive letter. >
414
415   mklink /D C:\testplugin E:
416 <
417 Close the administrator Command Prompt, and try running the command
418 `type C:\testplugin\LICENSE` in a new Command Prompt which you are NOT running
419 as administrator. You should see the license for ALE in your terminal. After
420 you have confirmed that you have mounted ALE on your machine, search in the
421 Start Menu for "power shell," run PowerShell as an administrator, and issue
422 the following commands to install the correct Vim and Vader versions for
423 running tests. >
424
425   Add-Type -A System.IO.Compression.FileSystem
426
427   Invoke-WebRequest ftp://ftp.vim.org/pub/vim/pc/vim80-586w32.zip -OutFile C:\vim.zip
428   [IO.Compression.ZipFile]::ExtractToDirectory('C:\vim.zip', 'C:\vim')
429   rm C:\vim.zip
430
431   Invoke-WebRequest ftp://ftp.vim.org/pub/vim/pc/vim80-586rt.zip -OutFile C:\rt.zip
432   [IO.Compression.ZipFile]::ExtractToDirectory('C:\rt.zip', 'C:\vim')
433   rm C:\rt.zip
434
435   Invoke-WebRequest https://github.com/junegunn/vader.vim/archive/c6243dd81c98350df4dec608fa972df98fa2a3af.zip -OutFile C:\vader.zip
436   [IO.Compression.ZipFile]::ExtractToDirectory('C:\vader.zip', 'C:\')
437   mv C:\vader.vim-c6243dd81c98350df4dec608fa972df98fa2a3af C:\vader
438   rm C:\vader.zip
439 <
440 After you have finished installing everything, you can run all of the tests
441 in Windows by opening a Command Prompt NOT as an administrator by navigating
442 to the directory where you've mounted the ALE code, which must be named
443 `C:\testplugin`, and by running the `run-tests.bat` batch file. >
444
445   cd C:\testplugin
446   run-tests
447 <
448 It will probably take several minutes for all of the tests to run. Be patient.
449 You can run a specific test by passing the filename as an argument to the
450 batch file, for example: `run-tests test/test_c_flag_parsing.vader` . This will
451 give you results much more quickly.
452
453
454 ===============================================================================
455 5. Contributing                                  *ale-development-contributing*
456
457 All integration of new code into ALE is done through GitHub pull requests.
458 Using that tool streamlines the process and minimizes the time and effort
459 required to e.g. ensure test suites are run for every change.
460
461 As for any project hosted by GitHub, the choice of platform demands every
462 contributor to take care to setup an account and configure it accordingly.
463
464 Due to details of our process, a difference to many other GitHub hosted
465 projects is that contributors who wish to keep the author fields for their
466 commits unaltered need to configure a public email address in their account
467 and profile settings. See: https://docs.github.com/en/account-and-profile/
468
469 Unless configuring GitHub to expose contact details, commits will be rewritten
470 to appear by `USERNAME <RANDOM_NUMBER+USERNAME@users.noreply.github.com>` .
471
472
473 ===============================================================================
474 5.1 Preparing a Release                               *ale-development-release*
475
476 ALE offers release packages through GitHub, for two reasons:
477
478 1. Some users like to target specific release versions rather than simply
479    installing the plugin from `master`. This includes users who create Linux
480    distribution specific packages from GitHub releases.
481 2. The releases provide a nice way to get an overview of what has changed in
482    ALE over time.
483
484 ALE has no fixed release schedule. Release versions are created whenever the
485 ALE developers feel the need to create one. ALE release versions follow the
486 typical Semantic Versioning scheme. See: https://semver.org/
487
488 Minor version releases for ALE should be the most common, followed by patch
489 releases. Every minor version release should be followed by a `vA.B.x` branch
490 such as `v2.0.x` for version `2.0.0` and every following patch version before
491 `2.1.0`. The `git` branch strategy for patches is to first merge a bug fix to
492 `master`, and then `git cherry-pick` a patch to a branch for a specific
493 version. ALE developers do not generally support anything but `master` or the
494 last minor version.
495
496 Generally ALE releases hit a major version only when there are breaking
497 changes to a public ALE setting or function. A "public" setting or function is
498 defined as any setting or function documented in the `:help` |ale.txt| file.
499 Major ALE versions ought to be so rare that they only come once a year at
500 most. ALE should not typically introduce any breaking changes.
501
502 If there are ever to be any breaking changes made for ALE, there should first
503 come a minor version release for ALE documenting all of the coming breaking
504 changes to ALE. It should be described how users can prepare for a breaking
505 change that is coming before it is done.
506
507 To create a release for ALE, you will need sufficient permissions in GitHub.
508 Once you do, follow these steps.
509
510 1. Create a new release draft, or edit an existing one. It helps to craft
511    drafts ahead of time and write the last commit ID checked for release notes
512    on the last update to a draft.
513    See the releases page: https://github.com/dense-analysis/ale/releases
514 2. Examine `git log` and read changes made between the last ID checked, or the
515    git tag of the previous release, and the current commit in `master`.
516 3. Write updates in separate sections (except where empty) for:
517   3.a. Breaking Changes
518   3.b. Deprecated Features
519   3.c. New Features
520   3.d. New Linters
521   3.e. New Fixers
522   3.f. Linter Enhancements
523   3.g. Fixer Enhancements
524   3.h. Bugs Fixed
525 4. Once you've finished writing the draft for the release, bump
526    `s:current_ale_version` in `autoload/ale.vim` to the current version, and
527    add a line to `test/test_ale_has.vader` to test for the version. See
528    |ale#Has()| documentation for more information.
529 5. Commit the changes after `./run-tests --fast -q` passes.
530 6. Tag the release with `git tag vA.B.C`, replacing `A`, `B`, and `C` with the
531    version numbers. See `git tag --list` for examples.
532 7. Run `git push` and `git push --tags` to push the commit and the tag.
533 8. Edit the release draft in GitHub, select the tag you just pushed, and
534    publish the draft.
535 9. If you're creating a new major or minor version: `git checkout -b vA.B.x`,
536    replacing `A` and `B` with the major and minor versions. `git push` the new
537    branch, and the GitHub branch protection settings should automatically
538    apply to the new release branch.
539 10. You have already completed the last step.
540
541 Have fun creating ALE releases. Drink responsibly, or not at all, which is the
542 preference of w0rp.
543
544
545 ===============================================================================
546   vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: