├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── addon-info.json ├── autoload ├── coverage.vim └── coverage │ ├── gcov.vim │ ├── gcov │ └── parsing.vim │ ├── python.vim │ └── vim.vim ├── bootstrap.vim ├── doc └── coverage.txt ├── instant └── flags.vim ├── plugin ├── commands.vim ├── coverage.vim └── mappings.vim ├── python └── vim_coverage.py └── vroom ├── lcov.vroom ├── main.vroom ├── python.vroom ├── setupvroom.vim └── testdata └── dummy.py /.gitignore: -------------------------------------------------------------------------------- 1 | /doc/tags 2 | *.pyc 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | env: 3 | matrix: 4 | # The requirement in plugin/coverage.vim is older, but testing in python3 5 | # environments requires maktaba python3 support added in 1.14.0. 6 | - CI_TARGET=vim MAKTABA_VERSION=1.14.0 7 | - CI_TARGET=vim MAKTABA_VERSION=master 8 | - CI_TARGET=neovim MAKTABA_VERSION=master 9 | before_script: 10 | - sudo apt-get update 11 | - sudo apt-get install python3-dev python3-coverage 12 | - if [ $CI_TARGET = vim ]; then 13 | sudo apt-get install vim-gnome; 14 | elif [ $CI_TARGET = neovim ]; then 15 | eval "$(curl -Ss https://raw.githubusercontent.com/neovim/bot-ci/master/scripts/travis-setup.sh) nightly-x64" && 16 | wget https://bootstrap.pypa.io/get-pip.py && 17 | sudo python3 get-pip.py && 18 | sudo pip3 install neovim; 19 | fi 20 | - wget https://github.com/google/vroom/releases/download/v0.13.0/vroom_0.13.0-1_all.deb 21 | - sudo dpkg -i ./vroom_0.13.0-1_all.deb 22 | - git clone -b ${MAKTABA_VERSION} https://github.com/google/vim-maktaba.git ../maktaba/ 23 | services: 24 | - xvfb 25 | script: 26 | - '[ $CI_TARGET = neovim ] && VROOM_ARGS="--neovim" || VROOM_ARGS=""' 27 | - vroom $VROOM_ARGS --crawl ./vroom/ 28 | matrix: 29 | fast_finish: true 30 | allow_failures: 31 | - env: CI_TARGET=neovim MAKTABA_VERSION=master 32 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributor License Agreement ## 2 | 3 | Patches and contributions are welcome. Before we can accept them, though, we 4 | have to see to the legal details. 5 | 6 | Contributions to any Google project must be accompanied by a Contributor 7 | License Agreement. This is not a copyright **assignment**, it simply gives 8 | Google permission to use and redistribute your contributions as part of the 9 | project. 10 | 11 | * If you are an individual writing original source code and you're sure you 12 | own the intellectual property, then you'll need to sign an [individual 13 | CLA][]. 14 | 15 | * If you work for a company that wants to allow you to contribute your work, 16 | then you'll need to sign a [corporate CLA][]. 17 | 18 | You generally only need to submit a CLA once, so if you've already submitted 19 | one (even if it was for a different project), you probably don't need to do it 20 | again. 21 | 22 | [individual CLA]: https://developers.google.com/open-source/cla/individual 23 | [corporate CLA]: https://developers.google.com/open-source/cla/corporate 24 | 25 | 26 | ## Submitting a patch ## 27 | 28 | 1. It's generally best to start by opening a new issue describing the bug or 29 | feature you're intending to fix. Even if you think it's relatively minor, 30 | it's helpful to know what people are working on. Mention in the initial 31 | issue that you are planning to work on that bug or feature so that it can 32 | be assigned to you. 33 | 34 | 1. Follow the normal process of [forking][] the project, and setup a new 35 | branch to work in. It's important that each group of changes be done in 36 | separate branches in order to ensure that a pull request only includes the 37 | commits related to that bug or feature. 38 | 39 | 1. Any significant changes should almost always be accompanied by tests. The 40 | project already has good test coverage, so look at some of the existing 41 | tests (in the `vroom/` directory) if you're unsure how to go about it. 42 | 43 | 1. Do your best to have [well-formed commit messages][] for each change. 44 | This provides consistency throughout the project, and ensures that commit 45 | messages are able to be formatted properly by various git tools. 46 | 47 | 1. Finally, push the commits to your fork and submit a [pull request][]. 48 | 49 | [forking]: https://help.github.com/articles/fork-a-repo 50 | [well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html 51 | [pull request]: https://help.github.com/articles/creating-a-pull-request 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vim-coverage is a utility for visualizing test coverage results in vim. 2 | vim-coverage relies on [maktaba](https://github.com/google/vim-maktaba) for 3 | registration and management of coverage providing plugins. 4 | 5 | For details, see the helpfiles in the `doc/` directory. The helpfiles are also 6 | available via `:help vim-coverage` if vim-coverage is installed (and helptags 7 | have been generated). 8 | 9 | # Commands 10 | 11 | Use `:CoverageShow` to show file coverage for the current buffer. Use 12 | `:CoverageToggle` to toggle coverage visibility for the current file. 13 | 14 | # Installation 15 | 16 | This example uses [Vundle](https://github.com/gmarik/Vundle.vim), whose 17 | plugin-adding command is `Plugin`. 18 | 19 | ```vim 20 | " Add maktaba and coverage to the runtimepath. 21 | " (The latter must be installed before it can be used.) 22 | Plugin 'google/vim-maktaba' 23 | Plugin 'google/vim-coverage' 24 | " Also add Glaive, which is used to configure coverage's maktaba flags. See 25 | " `:help :Glaive` for usage. 26 | Plugin 'google/vim-glaive' 27 | call glaive#Install() 28 | " Optional: Enable coverage's default mappings on the C prefix. 29 | Glaive coverage plugin[mappings] 30 | ``` 31 | 32 | Make sure you have updated maktaba recently. Older versions had an issue 33 | detecting installed libraries. 34 | 35 | # Using coverage providers 36 | 37 | The easiest way to see the list of available providers is via tab completion: 38 | Type `:CoverageShow ` in vim. 39 | 40 | To use a particular provider, type `:CoverageShow PROVIDER-NAME`. This will 41 | either show coverage in the current buffer using the selected provider or show 42 | an error message if provider is not available. Normally you will trigger 43 | providers via key mappings and/or autocommand hooks. 44 | 45 | vim-coverage currently defines several coverage providers: 46 | 1. A [coverage.py](https://coverage.readthedocs.io/) provider for python. 47 | 2. A [covimerage](https://github.com/Vimjas/covimerage) provider for vimscript. 48 | 3. A gcov provider for [gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html), which handles [lcov tracefiles](http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php). 49 | 50 | See https://github.com/google/vim-coverage/issues for other planned 51 | integrations. 52 | 53 | Coverage offers a lot of customization on colors and signs rendered for covered 54 | and uncovered lines. You can get a quick view of all coverage flags by executing 55 | `:Glaive coverage`, or start typing flag names and use tab completion. See 56 | `:help Glaive` for usage details. 57 | 58 | # Defining custom providers 59 | 60 | Any plugin wishing to be a coverage provider needs only to register itself using 61 | Maktaba's registry feature, passing a dictionary of following format: 62 | 63 | - `IsAvailable(filename)` - return `1` if plugin can handle the current file, 64 | otherwise `0`. 65 | - `GetCoverage(filename)` - returns the coverage dict created by 66 | `coverage#CreateReport` that contains all coverage data. 67 | - `name` - the name of the provider. 68 | - optional: `GetCoverageAsync(filename, callback)` - gets the coverage and 69 | once done, invokes the provided callback with the coverage dict created by 70 | `coverage#CreateReport` that contains all coverage data. 71 | 72 | Example: 73 | 74 | ```vim 75 | let s:registry = maktaba#extension#GetRegistry('coverage') 76 | call s:registry.AddExtension({ 77 | \ 'name': 'my_provider', 78 | \ 'GetCoverage': function('myplugin#GetCoverage'), 79 | \ 'GetCoverageAsync': function('myplugin#GetCoverageAsync'), 80 | \ 'IsAvailable': function('myplugin#IsAvailable')}) 81 | ``` 82 | -------------------------------------------------------------------------------- /addon-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coverage", 3 | "description": "Generic coverage reporter.", 4 | "version": "0.0.1", 5 | "repository": {"type": "git", "url": "git://github.com/google/vim-coverage"}, 6 | "dependencies": { 7 | "maktaba": {"type": "git", "url": "git://github.com/google/vim-maktaba"} 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /autoload/coverage.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2014 Google Inc. All rights reserved. 2 | " 3 | " Licensed under the Apache License, Version 2.0 (the "License"); 4 | " you may not use this file except in compliance with the License. 5 | " You may obtain a copy of the License at 6 | " 7 | " http://www.apache.org/licenses/LICENSE-2.0 8 | " 9 | " Unless required by applicable law or agreed to in writing, software 10 | " distributed under the License is distributed on an "AS IS" BASIS, 11 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | " See the License for the specific language governing permissions and 13 | " limitations under the License. 14 | 15 | "{{{ Init 16 | 17 | let s:plugin = maktaba#plugin#Get('coverage') 18 | let s:registry = s:plugin.GetExtensionRegistry() 19 | if !exists('s:visible') 20 | " Buffer paths for which the coverage is visible. 21 | let s:visible = {} 22 | endif 23 | if !exists('s:cache') 24 | " Cache of retrieved coverage data per path. 25 | let s:cache = {} 26 | endif 27 | if !exists('s:coverage_states') 28 | let s:coverage_states = ['covered', 'uncovered', 'partial'] 29 | endif 30 | 31 | "}}} 32 | 33 | "{{{ coverage utility functions 34 | 35 | "" 36 | " Places the signs at given {lines} in given {state}. 37 | function! s:ColorSigns(lines, state) abort 38 | for l:num in a:lines 39 | execute ':sign place ' . l:num . ' line=' . l:num . 40 | \ ' name=sign_' . a:state . ' file=' . expand('%') 41 | endfor 42 | endfunction 43 | 44 | 45 | "" 46 | " Defines highlighting rules for coverage colors and defines text signs for each 47 | " coverage state, as defined via plugin flags. See |coverage-config|. 48 | function! s:DefineHighlighting() abort 49 | if !hlexists('coverage_covered') 50 | for l:state in s:coverage_states 51 | execute 'highlight coverage_' . l:state . 52 | \ ' ctermbg=' . s:plugin.Flag(l:state . '_ctermbg') . 53 | \ ' ctermfg=' . s:plugin.Flag(l:state . '_ctermfg') . 54 | \ ' guibg=' . s:plugin.Flag(l:state . '_guibg') . 55 | \ ' guifg=' . s:plugin.Flag(l:state . '_guifg') 56 | execute 'sign define sign_' . l:state . ' text=' . 57 | \ s:plugin.Flag(l:state . '_text') . ' texthl=coverage_' . l:state 58 | endfor 59 | endif 60 | endfunction 61 | 62 | 63 | "" 64 | " Renders the coverage for the required {filename}. Coverage needs to be in 65 | " cache. This function does not get the coverage itself, only displays it. 66 | " If [show_stats] is set, the coverage stats are shown, e.g. Coverage 70%(7/10). 67 | " @default show_stats=1 68 | function! s:RenderFromCache(filename, ...) abort 69 | let l:show_stats = maktaba#ensure#IsBool(get(a:, 1, 1)) 70 | call s:DefineHighlighting() 71 | if (has_key(s:cache, a:filename)) 72 | let l:data = s:cache[a:filename] 73 | for l:state in s:coverage_states 74 | call s:ColorSigns(l:data[l:state], l:state) 75 | endfor 76 | if l:show_stats 77 | echomsg coverage#GetFormattedStats(a:filename) 78 | endif 79 | let s:visible[expand('%:p')] = 1 80 | endif 81 | endfunction 82 | 83 | 84 | "" 85 | " Hides coverage layer. 86 | function! s:CoverageHide() abort 87 | if has_key(s:visible, expand('%:p')) 88 | execute 'sign unplace * file=' . expand('%:p') 89 | unlet s:visible[expand('%:p')] 90 | endif 91 | endfunction 92 | 93 | 94 | "" 95 | " Toggles coverage layer. 96 | function! s:CoverageToggle(skip_cache) abort 97 | if has_key(s:visible, expand('%:p')) 98 | call s:CoverageHide() 99 | else 100 | call s:CoverageShow(a:skip_cache) 101 | endif 102 | endfunction 103 | 104 | 105 | "" 106 | " Shows coverage layer. If [explicit_provider] is set, it will be used for 107 | " fetching the coverage data. 108 | function! s:CoverageShow(skip_cache, ...) abort 109 | let l:filename = expand('%:p') 110 | 111 | if has_key(s:visible, l:filename) 112 | if a:skip_cache 113 | call s:CoverageHide() 114 | else 115 | " This file is already being shown, no need to re-show. 116 | return 117 | endif 118 | endif 119 | 120 | if has_key(s:cache, l:filename) && !a:skip_cache 121 | call s:RenderFromCache(l:filename) 122 | return 123 | endif 124 | 125 | if a:0 > 0 126 | let l:provider = maktaba#ensure#IsString(a:1) 127 | call coverage#ShowCoverage(l:provider) 128 | else 129 | call coverage#ShowCoverage() 130 | endif 131 | 132 | endfunction 133 | 134 | "" 135 | " Shows coverage in vimdiff with the version coverage was known for. 136 | function! s:CoverageShowDiff() abort 137 | let l:filename = expand('%:p') 138 | if has_key(s:cache, l:filename) 139 | let l:data = s:cache[l:filename] 140 | if has_key(l:data, 'diff_path') 141 | " Current file has changed, so split into diff mode with the file at the 142 | " point where the coverage is known, and render it there, in the split. 143 | execute 'vertical' 'diffsplit' l:data.diff_path 144 | call s:RenderFromCache(l:filename) 145 | else 146 | call maktaba#error#Warn('There is no diff.') 147 | endif 148 | endif 149 | endfunction 150 | 151 | 152 | "" 153 | " Calculates coverage stats from @dict(s:cache), and returns the stats for the 154 | " requested {filename}. Does not get the coverage stats. 155 | function! coverage#GetFormattedStats(filename) abort 156 | if has_key(s:cache, a:filename) 157 | let l:data = s:cache[a:filename] 158 | let l:stats = {'total': 0} 159 | for l:state in s:coverage_states 160 | let l:stats[l:state] = len(l:data[l:state]) 161 | let l:stats['total'] += len(l:data[l:state]) 162 | endfor 163 | if l:stats.total is 0 164 | return printf('Coverage is empty for file %s.', a:filename) 165 | endif 166 | let l:percentage = 100.0 * l:stats.covered / l:stats.total 167 | return printf('Coverage is %.2f%% (%d/%d lines).', 168 | \ l:percentage, l:stats.covered, l:stats.total) 169 | endif 170 | endfunction 171 | 172 | 173 | "" 174 | " @public 175 | " Returns a coverage report compatible with |coverage|, for {covered}, 176 | " {uncovered} and {partial} lines. Optional param [extra_dict] can be passed in, 177 | " which will be merged with the result. 178 | function! coverage#CreateReport(covered, uncovered, partial, ...) abort 179 | let l:extra_dict = {} 180 | if a:0 > 0 181 | let l:extra_dict = maktaba#ensure#IsDict(a:1) 182 | endif 183 | call maktaba#ensure#IsList(a:covered) 184 | call maktaba#ensure#IsList(a:uncovered) 185 | call maktaba#ensure#IsList(a:partial) 186 | return extend(l:extra_dict, 187 | \ {'covered': a:covered, 188 | \ 'uncovered': a:uncovered, 189 | \ 'partial': a:partial}) 190 | endfunction 191 | 192 | 193 | "" 194 | " Renders coverage for the current file. A name of a registered [provider] can 195 | " be passed as a parameter. If left blank, buffer b:coverage_provider variable 196 | " will be first checked, and if it is not set, then the first registered 197 | " provider will be used. If the provider defines a 198 | " @function(provider#GetCoverageAsync), it is preferred. The callback must have 199 | " function(coverage_data) prototype. Coverage data format is as described in 200 | " the general help for this plugin. 201 | " @default provider=b:coverage_provider or first registered provider 202 | " @throws NotFound if requested provider is not found or non are registered, or 203 | " the is not available for the current file. 204 | function! coverage#ShowCoverage(...) abort 205 | let l:filename = expand('%:p') 206 | let l:providers = s:registry.GetExtensions() 207 | if a:0 >= 1 208 | let l:explicit_name = a:1 209 | elseif !empty(get(b:, 'coverage_provider')) 210 | let l:explicit_name = b:coverage_provider 211 | elseif len(l:providers) > 0 212 | for l:provider in l:providers 213 | if l:provider.IsAvailable(l:filename) 214 | let l:default_provider = l:provider 215 | break 216 | endif 217 | endfor 218 | if !exists('l:default_provider') 219 | throw maktaba#error#NotFound('No available coverage providers.') 220 | endif 221 | let l:selected_provider = l:default_provider 222 | else 223 | throw maktaba#error#NotFound('No registered coverage providers.') 224 | endif 225 | 226 | if exists('l:explicit_name') 227 | for l:provider in l:providers 228 | if l:provider.name ==# l:explicit_name 229 | let l:explicit_provider = l:provider 230 | break 231 | endif 232 | endfor 233 | if !exists('l:explicit_provider') 234 | throw maktaba#error#NotFound('Coverage provider %s not found.', 235 | \ l:explicit_name) 236 | endif 237 | let l:selected_provider = l:explicit_provider 238 | endif 239 | 240 | if !l:selected_provider.IsAvailable(l:filename) 241 | throw maktaba#error#NotFound('Provider %s is not available for file %s', 242 | \ l:explicit_name, l:filename) 243 | endif 244 | let l:callback = maktaba#function#Create('coverage#CacheAndShow', 245 | \ [l:filename]) 246 | if has_key(l:selected_provider, 'GetCoverageAsync') 247 | call l:selected_provider.GetCoverageAsync(l:filename, l:callback) 248 | else 249 | call maktaba#function#Apply(l:callback, 250 | \ l:selected_provider.GetCoverage(l:filename)) 251 | endif 252 | endfunction 253 | 254 | "" 255 | " Caches the {coverage} for the {filename} and renders it. This can be used as a 256 | " callback entry for asynchronous calls. {coverage} format is as described in 257 | " the general help for this plugin. 258 | function! coverage#CacheAndShow(filename, coverage) abort 259 | if !maktaba#value#IsDict(a:coverage) 260 | return 261 | endif 262 | let s:cache[a:filename] = a:coverage 263 | if !has_key(a:coverage, 'diff_path') 264 | call s:RenderFromCache(a:filename) 265 | endif 266 | endfunction 267 | 268 | "}}} 269 | 270 | "{{{ Misc 271 | 272 | function! coverage#Toggle(skip_cache) abort 273 | call s:CoverageToggle(a:skip_cache) 274 | endfunction 275 | 276 | function! coverage#Show(skip_cache, ...) abort 277 | try 278 | if a:0 > 0 279 | call s:CoverageShow(a:skip_cache, a:1) 280 | else 281 | call s:CoverageShow(a:skip_cache) 282 | endif 283 | catch /ERROR.*/ 284 | call maktaba#error#Shout('Error rendering coverage: %s', v:exception) 285 | endtry 286 | endfunction 287 | 288 | function! coverage#ShowDiff() abort 289 | try 290 | call s:CoverageShowDiff() 291 | catch /ERROR.*/ 292 | call maktaba#error#Shout('Error rendering coverage: %s', v:exception) 293 | endtry 294 | endfunction 295 | 296 | function! coverage#Hide() abort 297 | try 298 | if has_key(s:visible, expand('%:p')) 299 | call s:CoverageHide() 300 | endif 301 | catch /ERROR.*/ 302 | call maktaba#error#Shout('Error rendering coverage: %s', v:exception) 303 | endtry 304 | endfunction 305 | 306 | "" 307 | " @private 308 | " Completions for the available providers. Returns a list of providers that 309 | " start with {arg}. 310 | function! coverage#CompletionList(arg, line, pos) abort 311 | let l:providers = [] 312 | for l:extension in s:registry.GetExtensions() 313 | call add(l:providers, l:extension.name) 314 | endfor 315 | return filter(l:providers, 'maktaba#string#StartsWith(v:val, a:arg)') 316 | endfunction 317 | 318 | "" 319 | " Makes sure the coverage {provider} is a valid provider for the plugin. 320 | " @throws BadValue if the provider is not valid. 321 | function! coverage#EnsureProvider(provider) abort 322 | let l:required_fields = ['name', 'IsAvailable', 'GetCoverage'] 323 | " Throw BadValue if any required fields are missing. 324 | let l:missing_fields = 325 | \ filter(copy(l:required_fields), '!has_key(a:provider, v:val)') 326 | if !empty(l:missing_fields) 327 | throw maktaba#error#BadValue( 328 | \ 'Provider is missing fields: %s. Got: %s', 329 | \ join(l:missing_fields, ', '), 330 | \ string(a:provider)) 331 | endif 332 | endfunction 333 | 334 | "}}} 335 | -------------------------------------------------------------------------------- /autoload/coverage/gcov.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2021 Google Inc. All rights reserved. 2 | " 3 | " Licensed under the Apache License, Version 2.0 (the "License"); 4 | " you may not use this file except in compliance with the License. 5 | " You may obtain a copy of the License at 6 | " 7 | " http://www.apache.org/licenses/LICENSE-2.0 8 | " 9 | " Unless required by applicable law or agreed to in writing, software 10 | " distributed under the License is distributed on an "AS IS" BASIS, 11 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | " See the License for the specific language governing permissions and 13 | " limitations under the License. 14 | 15 | "{{{ Init 16 | 17 | let s:plugin = maktaba#plugin#Get('coverage') 18 | 19 | "" 20 | " Directories under which to shallowly search for gcov data files. 21 | " 22 | " Temporary, to be removed in https://github.com/google/vim-coverage/issues/42 23 | if !has_key(s:plugin.globals, '_gcov_temp_search_paths') 24 | let s:plugin.globals._gcov_temp_search_paths = ['.'] 25 | endif 26 | 27 | "" 28 | " A list of |glob()| expressions representing gcov info files. 29 | " Files must be in the format produced by gcov's geninfo utility. 30 | " 31 | " Temporary, to be removed in https://github.com/google/vim-coverage/issues/42 32 | if !has_key(s:plugin.globals, '_gcov_temp_file_patterns') 33 | let s:plugin.globals._gcov_temp_file_patterns = [ 34 | \ '*.gcda.info', 35 | \ 'coverage.dat', 36 | \ '_coverage_report.dat' 37 | \ ] 38 | endif 39 | 40 | "}}} 41 | 42 | "{{{ [gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html) coverage provider. 43 | 44 | "" 45 | " @private 46 | " Gets a list of files matching the plugin settings. 47 | function! s:GetCoverageInfoFiles() abort 48 | let l:paths = join(s:plugin.globals._gcov_temp_search_paths, ',') 49 | let l:info_files = [] 50 | for l:gcov_file_pattern in s:plugin.globals._gcov_temp_file_patterns 51 | call extend( 52 | \ l:info_files, 53 | \ globpath(l:paths, l:gcov_file_pattern, 0, 1)) 54 | endfor 55 | return l:info_files 56 | endfunction 57 | 58 | "" 59 | " @private 60 | " Concatenates coverage reports from 'source' into 'destination'. 61 | function! s:ExtendReport(destination, source) 62 | call extend(a:destination.covered, a:source.covered) 63 | call extend(a:destination.partial, a:source.partial) 64 | call extend(a:destination.uncovered, a:source.uncovered) 65 | endfunction 66 | 67 | "" 68 | " @private 69 | " Gets a dictionary of coverage reports based on all gcov files matching the 70 | " plugin configuration. 71 | function! s:GetReports() abort 72 | let l:reports = {} 73 | 74 | for l:info_file in s:GetCoverageInfoFiles() 75 | let l:parsed_reports = coverage#gcov#parsing#ParseLcovFile(l:info_file) 76 | for [l:filename, l:report] in l:parsed_reports 77 | if has_key(l:reports, l:filename) 78 | call s:ExtendReport(l:reports[l:filename], l:report) 79 | else 80 | let l:reports[l:filename] = l:report 81 | endif 82 | endfor 83 | endfor 84 | 85 | for l:report in values(l:reports) 86 | call s:CleanReport(l:report) 87 | endfor 88 | return l:reports 89 | endfunction 90 | 91 | "" 92 | " @private 93 | " Removes duplicates from the given report, and deals with conflicting coverage 94 | " files that may say a line is partially covered/uncovered, where another report 95 | " shows it as covered. 96 | function! s:CleanReport(report) abort 97 | call uniq(a:report.covered) 98 | call uniq(a:report.partial) 99 | call uniq(a:report.uncovered) 100 | " Only keep 'partial' lines that are not in 'covered' 101 | call filter(a:report.partial, 'index(a:report.covered, v:val) < 0') 102 | " Only keep 'uncovered' lines that are not in 'partial' or 'covered' 103 | call filter(a:report.uncovered, 104 | \ 'index(a:report.partial, v:val) < 0 ' . 105 | \ '&& index(a:report.covered, v:val) < 0') 106 | endfunction 107 | 108 | "" 109 | " @public 110 | " Produces a provider dictionary for the gcov plugin. 111 | function! coverage#gcov#GetGcovProvider() abort 112 | let l:provider = {'name': 'gcov'} 113 | 114 | "" 115 | " Returns whether the coverage provider is available for the current file. 116 | " 117 | " This checks if there are any gcov-like files in the configured set of files. 118 | " We can't check specifically for this filename unless we read each of those 119 | " files, too. 120 | function l:provider.IsAvailable(unused_filename) abort 121 | call maktaba#ensure#IsList(s:plugin.globals._gcov_temp_search_paths) 122 | call maktaba#ensure#IsList(s:plugin.globals._gcov_temp_file_patterns) 123 | return !empty(s:GetCoverageInfoFiles()) 124 | endfunction 125 | 126 | function l:provider.GetCoverage(filename) abort 127 | let l:reports = s:GetReports() 128 | for [l:covered_file, l:report] in items(l:reports) 129 | if maktaba#string#EndsWith(a:filename, l:covered_file) 130 | return l:report 131 | endif 132 | endfor 133 | endfunction 134 | 135 | return l:provider 136 | endfunction 137 | 138 | "}}} 139 | -------------------------------------------------------------------------------- /autoload/coverage/gcov/parsing.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2021 Google Inc. All rights reserved. 2 | " 3 | " Licensed under the Apache License, Version 2.0 (the "License"); 4 | " you may not use this file except in compliance with the License. 5 | " You may obtain a copy of the License at 6 | " 7 | " http://www.apache.org/licenses/LICENSE-2.0 8 | " 9 | " Unless required by applicable law or agreed to in writing, software 10 | " distributed under the License is distributed on an "AS IS" BASIS, 11 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | " See the License for the specific language governing permissions and 13 | " limitations under the License. 14 | 15 | "{{{ Init 16 | 17 | let s:plugin = maktaba#plugin#Get('coverage') 18 | 19 | "}}} 20 | 21 | "{{{ Utility functions for parsing gcov files (i.e. lcov tracefiles). 22 | 23 | "" 24 | " @private 25 | " Categorizes a line potentially containing coverage information in a coverage 26 | " file. Recognized coverage information is be formatted as: 27 | " - DA:,[,] 28 | " - BA:, 29 | " - BRDA:,,, 30 | " 31 | " Note that for BRDA lines, we can't check for partial coverage (only '-' for 32 | " uncovered, or 1+ for the number of times the line was run). 33 | " 34 | " For additional details on lcov's tracefile format, see FILES under on 35 | " geninfo's man page, or view the man page at: 36 | " http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php 37 | function! s:TryParseLine(line) abort 38 | let [l:prefix; l:raw_info] = split(a:line, ':', 1) 39 | let l:raw_info = join(l:raw_info, ':') 40 | let l:prefix = maktaba#string#Strip(l:prefix) 41 | 42 | if l:prefix ==? 'BA' || l:prefix ==? 'DA' 43 | let l:hits_index = 1 44 | elseif l:prefix ==? 'BRDA' 45 | let l:hits_index = 3 46 | else 47 | return [] 48 | endif 49 | 50 | try 51 | let l:info = split(l:raw_info, ',', 1) 52 | let l:linenum = str2nr(info[0]) 53 | " Note that For BRDA lines, '-' is used instead of '0' for uncovered, which 54 | " str2nr will safely convert to 0. 55 | let l:hits = str2nr(info[l:hits_index]) 56 | catch 57 | call s:plugin.logger.Debug( 58 | \ 'Failed to parse gcov line (%s): %s', v:exception, a:line) 59 | return [] 60 | endtry 61 | 62 | if l:hits is 0 63 | return ['uncovered', l:linenum] 64 | endif 65 | 66 | if l:hits is 1 && l:prefix ==? 'BA' 67 | return ['partial', l:linenum] 68 | endif 69 | 70 | return ['covered', l:linenum] 71 | endfunction 72 | 73 | "" 74 | " @private 75 | " Gets a list of covered filenames and reports for a given lcov tracefile. 76 | " 77 | " For example: 78 | " [ 79 | " ['src/foo.c', {'covered': [1, 4], 'partial': [2], 'uncovered': []}], 80 | " ['src/bar.c', {'covered': [], 'partial': [], 'uncovered': [3, 4, 5]}], 81 | " ['src/bat.c', {'covered': [], 'partial': [], 'uncovered': []}], 82 | " ] 83 | " 84 | " If the plugin cannot find any tracefiles, [] will be returned. If a 85 | " tracefile has an empty record, it will be represented as an empty coverage 86 | " dict (as with bat.c above). 87 | " 88 | " Each coverage info file may contain multiple reports for different source 89 | " files. 90 | " 91 | " Data may be formatted as: 92 | " - SF: Starts a coverage section for a file 93 | " - Coverage data (see s:TryParseLine) 94 | " - end_of_record: End of a coverage section for a file 95 | function! coverage#gcov#parsing#ParseLcovFile(info_file) 96 | \ abort 97 | let l:reports = [] 98 | let l:lines = readfile(a:info_file) 99 | 100 | let l:current_file = -1 101 | let l:current_report = -1 102 | 103 | for l:line in l:lines 104 | let l:line = maktaba#string#Strip(l:line) 105 | 106 | " SF: 107 | " Begins a section of coverage. 108 | let l:maybe_prefix = split(l:line, ':', 1)[0] 109 | if maktaba#string#Strip(l:maybe_prefix) ==? 'SF' 110 | let l:current_file = maktaba#string#Strip( 111 | \ l:line[strlen(l:maybe_prefix) + 1:]) 112 | let l:current_report = coverage#CreateReport([], [], []) 113 | continue 114 | endif 115 | 116 | if l:current_file is -1 117 | continue 118 | endif 119 | 120 | if l:line ==? 'end_of_record' 121 | " Individual reports may have multiple rows for one line. 122 | " They may indicate that a line is covered (DA), but may also provide 123 | " branch information in a separate line (BA). 124 | " 125 | " In that case, within the report, we want to go with the partial data 126 | " over the covered data. 127 | call filter(l:current_report.covered, 128 | \ 'index(l:current_report.partial, v:val) < 0') 129 | 130 | call add(l:reports, [l:current_file, l:current_report]) 131 | 132 | let l:current_file = -1 133 | let l:current_report = -1 134 | continue 135 | endif 136 | 137 | let l:parsed_line = s:TryParseLine(l:line) 138 | if !empty(l:parsed_line) 139 | let [l:coverage_type, l:linenum] = l:parsed_line 140 | call add(l:current_report[l:coverage_type], l:linenum) 141 | endif 142 | endfor 143 | 144 | return l:reports 145 | endfunction 146 | 147 | "}}} 148 | -------------------------------------------------------------------------------- /autoload/coverage/python.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2017 Google Inc. All rights reserved. 2 | " 3 | " Licensed under the Apache License, Version 2.0 (the "License"); 4 | " you may not use this file except in compliance with the License. 5 | " You may obtain a copy of the License at 6 | " 7 | " http://www.apache.org/licenses/LICENSE-2.0 8 | " 9 | " Unless required by applicable law or agreed to in writing, software 10 | " distributed under the License is distributed on an "AS IS" BASIS, 11 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | " See the License for the specific language governing permissions and 13 | " limitations under the License. 14 | 15 | "{{{ Init 16 | 17 | let s:plugin = maktaba#plugin#Get('coverage') 18 | 19 | "}}} 20 | 21 | "{{{ coverage.py provider 22 | 23 | function! s:GetCoverageFile() abort 24 | " TODO(dbarnett): Limit upward search with some heuristics. 25 | return fnamemodify(findfile('.coverage', ';'), ':p') 26 | endfunction 27 | 28 | let s:imported_python = 0 29 | 30 | function! coverage#python#GetCoveragePyProvider() abort 31 | let l:provider = { 32 | \ 'name': 'coverage.py'} 33 | 34 | function l:provider.IsAvailable(unused_filename) abort 35 | return &filetype is# 'python' 36 | endfunction 37 | 38 | function l:provider.GetCoverage(filename) abort 39 | if !s:imported_python 40 | try 41 | call maktaba#python#ImportModule(s:plugin, 'vim_coverage') 42 | catch /ERROR.*/ 43 | throw maktaba#error#NotFound( 44 | \ "Couldn't import Python coverage module (%s). " . 45 | \ 'Install the coverage package and try again.', v:exception) 46 | endtry 47 | let s:imported_python = 1 48 | endif 49 | let l:cov_file = s:GetCoverageFile() 50 | if empty(l:cov_file) 51 | throw maktaba#error#NotFound( 52 | \ 'No .coverage file found. ' . 53 | \ 'Generate one by running nosetests --with-coverage') 54 | endif 55 | let l:coverage_data = maktaba#python#Eval(printf( 56 | \ 'vim_coverage.GetCoveragePyLines(%s, %s)', 57 | \ string(l:cov_file), 58 | \ string(a:filename))) 59 | let [l:covered_lines, l:uncovered_lines] = l:coverage_data 60 | return coverage#CreateReport(l:covered_lines, l:uncovered_lines, []) 61 | endfunction 62 | 63 | return l:provider 64 | endfunction 65 | 66 | "}}} 67 | -------------------------------------------------------------------------------- /autoload/coverage/vim.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2017 Google Inc. All rights reserved. 2 | " 3 | " Licensed under the Apache License, Version 2.0 (the "License"); 4 | " you may not use this file except in compliance with the License. 5 | " You may obtain a copy of the License at 6 | " 7 | " http://www.apache.org/licenses/LICENSE-2.0 8 | " 9 | " Unless required by applicable law or agreed to in writing, software 10 | " distributed under the License is distributed on an "AS IS" BASIS, 11 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | " See the License for the specific language governing permissions and 13 | " limitations under the License. 14 | 15 | "{{{ [covimerage](https://github.com/Vimjas/covimerage) provider. 16 | " (based on coverage.py) 17 | 18 | function! coverage#vim#GetCovimerageProvider() abort 19 | let l:provider = extend(copy(coverage#python#GetCoveragePyProvider()), { 20 | \ 'name': 'covimerage'}) 21 | 22 | function! l:provider.IsAvailable(unused_filename) abort 23 | return &filetype is# 'vim' 24 | endfunction 25 | 26 | return l:provider 27 | endfunction 28 | 29 | "}}} 30 | -------------------------------------------------------------------------------- /bootstrap.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2014 Google Inc. All rights reserved. 2 | " 3 | " Licensed under the Apache License, Version 2.0 (the "License"); 4 | " you may not use this file except in compliance with the License. 5 | " You may obtain a copy of the License at 6 | " 7 | " http://www.apache.org/licenses/LICENSE-2.0 8 | " 9 | " Unless required by applicable law or agreed to in writing, software 10 | " distributed under the License is distributed on an "AS IS" BASIS, 11 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | " See the License for the specific language governing permissions and 13 | " limitations under the License. 14 | 15 | " This file can be sourced to install the plugin and its dependencies if no 16 | " plugin manager is available. 17 | 18 | let s:plugin_path = expand(':p:h') 19 | 20 | if !exists('*maktaba#compatibility#Disable') 21 | try 22 | " To check if Maktaba is loaded we must try calling a maktaba function. 23 | " exists() is false for autoloadable functions that are not yet loaded. 24 | call maktaba#compatibility#Disable() 25 | catch /E117:/ 26 | " Maktaba is not installed. Check whether it's in a nearby directory. 27 | let s:rtpsave = &runtimepath 28 | " We'd like to use maktaba#path#Join, but maktaba doesn't exist yet. 29 | let s:slash = exists('+shellslash') && !&shellslash ? '\' : '/' 30 | let s:guess1 = fnamemodify(s:plugin_path, ':h') . s:slash . 'maktaba' 31 | let s:guess2 = fnamemodify(s:plugin_path, ':h') . s:slash . 'vim-maktaba' 32 | if isdirectory(s:guess1) 33 | let &runtimepath .= ',' . s:guess1 34 | elseif isdirectory(s:guess2) 35 | let &runtimepath .= ',' . s:guess2 36 | endif 37 | 38 | try 39 | " If we've just installed maktaba, we need to make sure that vi 40 | " compatibility mode is off. Maktaba does not support vi compatibility. 41 | call maktaba#compatibility#Disable() 42 | catch /E117:/ 43 | " No luck. 44 | let &runtimepath = s:rtpsave 45 | unlet s:rtpsave 46 | " We'd like to use maktaba#error#Shout, but maktaba doesn't exist yet. 47 | echohl ErrorMsg 48 | echomsg 'Maktaba not found, but coverage requires it. Please either:' 49 | echomsg '1. Place maktaba in the same directory as this plugin.' 50 | echomsg '2. Add maktaba to your runtimepath before using this plugin.' 51 | echomsg 'Maktaba can be found at https://github.com/google/vim-maktaba.' 52 | echohl NONE 53 | finish 54 | endtry 55 | endtry 56 | endif 57 | call maktaba#plugin#GetOrInstall(s:plugin_path) 58 | -------------------------------------------------------------------------------- /doc/coverage.txt: -------------------------------------------------------------------------------- 1 | *coverage.txt* Generic coverage reporter. 2 | *Coverage* *coverage* 3 | 4 | ============================================================================== 5 | CONTENTS *coverage-contents* 6 | 1. Introduction.............................................|coverage-intro| 7 | 2. Usage....................................................|coverage-usage| 8 | 3. Configuration...........................................|coverage-config| 9 | 4. Commands..............................................|coverage-commands| 10 | 5. Functions............................................|coverage-functions| 11 | 12 | ============================================================================== 13 | INTRODUCTION *coverage-intro* 14 | 15 | Coverage is a generic vim coverage layer plugin. It depends upon |Maktaba|. 16 | 17 | Everybody knows test coverage is important. It is not paramount and you should 18 | not strive to cover every line, rather to cover sensible usecases, but it is 19 | still important to spot untested branches and code paths. 20 | 21 | Coverage report uses three colors: 22 | 23 | * red - line not covered 24 | * partial - branch taken, but not in all paths 25 | * green - fully covered 26 | 27 | See more about branch coverage on http://en.wikipedia.org/wiki/Code_coverage 28 | 29 | ============================================================================== 30 | USAGE *coverage-usage* 31 | 32 | 33 | To use this plugin, you need at least one coverage provider registered with 34 | it. This plugin provides a generic way to show coverage report line-by-line, 35 | but it requires a source of the information. Any plugin wishing to be a 36 | coverage provider needs only to register itself using 37 | |coverage#AddProvider()|, and pass a |Dictionary| with the following 38 | |Dictionary-function| defined: 39 | IsAvailable(filename) - return 1 if plugin can handle the current file, 40 | otherwise 0. 41 | GetCoverage(filename) - returns the coverage dict created by 42 | |coverage#CreateReport()| that contains all coverage data. 43 | Name() - returns the name of the plugin. 44 | optional: GetCoverageAsync(filename, callback) - gets the coverage and once 45 | done, invokes the provided callback with the coverage dict created by 46 | |coverage#CreateReport()| that contains all coverage data. 47 | 48 | You can define a mapping to toggle showing coverage report. To use the default 49 | mapping of "Ct", add the following to your vimrc: 50 | > 51 | Glaive coverage plugin[mappings] 52 | < 53 | 54 | ============================================================================== 55 | CONFIGURATION *coverage-config* 56 | 57 | This plugin uses maktaba flags for configuration. Install Glaive 58 | (https://github.com/google/glaive) and use the |:Glaive| command to configure 59 | them. 60 | 61 | *coverage:partial_text* 62 | Text shown on the sign of a partially-covered line (e.g. unexplored branch). 63 | Default: '◊◊' ` 64 | 65 | *coverage:uncovered_text* 66 | Text shown on the sign of a noncovered line (left of the line, in the corner). 67 | Default: '▵▵' ` 68 | 69 | *coverage:covered_text* 70 | Text shown on the sign of a covered line (left of the line, in the corner). 71 | Default: '▴▴' ` 72 | 73 | *coverage:partial_ctermbg* 74 | Background color for the partially covered lines when in cterm mode (non-GUI). 75 | Default: 'yellow' ` 76 | 77 | *coverage:partial_ctermfg* 78 | Text color for the partially covered lines when in cterm mode (non-GUI). 79 | Default: 'black' ` 80 | 81 | *coverage:partial_guibg* 82 | Background color for the partially covered lines when in GUI mode (e.g. gvim). 83 | Default: 'yellow' ` 84 | 85 | *coverage:partial_guifg* 86 | Text color for the partially covered lines when in GUI mode (e.g. gvim). 87 | Default: 'black' ` 88 | 89 | *coverage:covered_ctermbg* 90 | Background color for the covered lines when in cterm mode (non-GUI). 91 | Default: 'lightgreen' ` 92 | 93 | *coverage:covered_ctermfg* 94 | Text color for the covered lines when in cterm mode (non-GUI). 95 | Default: 'black' ` 96 | 97 | *coverage:covered_guibg* 98 | Background color for the covered lines when in GUI mode (e.g. gvim). 99 | Default: 'green' ` 100 | 101 | *coverage:covered_guifg* 102 | Text color for the covered lines when in GUI mode (e.g. gvim). 103 | Default: 'black' ` 104 | 105 | *coverage:uncovered_ctermbg* 106 | Background color for the uncovered lines when in cterm mode (non-GUI). 107 | Default: 'red' ` 108 | 109 | *coverage:uncovered_ctermfg* 110 | Text color for the uncovered lines when in cterm mode (non-GUI). 111 | Default: 'white' ` 112 | 113 | *coverage:uncovered_guibg* 114 | Background color for the uncovered lines when in GUI mode (e.g. gvim). 115 | Default: 'red' ` 116 | 117 | *coverage:uncovered_guifg* 118 | Text color for the uncovered lines when in GUI mode (e.g. gvim). 119 | Default: 'white' ` 120 | 121 | *coverage:plugin[commands]* 122 | Configures whether plugin/commands.vim should be loaded. 123 | Default: 1 ` 124 | 125 | *coverage:plugin[coverage]* 126 | Configures whether plugin/coverage.vim should be loaded. 127 | Default: 1 ` 128 | 129 | *coverage:plugin[mappings]* 130 | Configures whether plugin/mappings.vim should be loaded. 131 | Default: 0 ` 132 | 133 | ============================================================================== 134 | COMMANDS *coverage-commands* 135 | 136 | For toggling coverage view, the t mapping is set. To automatically 137 | render coverage for available file types, create an autocmd, e.g.: 138 | > 139 | augroup coverage 140 | autocmd! 141 | autocmd BufReadPost *.py,*.c,*.cc,*.h,*.java,*.go,*.js :CoverageShow 142 | augroup END 143 | < 144 | 145 | This will render coverage for all mentioned filetypes, if available. 146 | 147 | :CoverageShow *:CoverageShow* 148 | Show coverage report. If variable b:coverage_provider is set, the provider 149 | from it will be used. 150 | 151 | :CoverageToggle *:CoverageToggle* 152 | Toggle coverage report. 153 | 154 | :CoverageShowDiff *:CoverageShowDiff* 155 | Show coverage report when the file changed, using vimdiff. 156 | 157 | :CoverageHide *:CoverageHide* 158 | Hide coverage report. 159 | 160 | :CoverageStats *:CoverageStats* 161 | Print formatted stats, e.g. Coverage 88% (22/25 lines). 162 | 163 | ============================================================================== 164 | FUNCTIONS *coverage-functions* 165 | 166 | coverage#CreateReport({covered}, {uncovered}, {partial}, [extra_dict]) 167 | *coverage#CreateReport()* 168 | Returns a coverage report compatible with |coverage|, for {covered}, 169 | {uncovered} and {partial} lines. Optional param [extra_dict] can be passed 170 | in, which will be merged with the result. 171 | 172 | 173 | vim:tw=78:ts=8:ft=help:norl: 174 | -------------------------------------------------------------------------------- /instant/flags.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2014 Google Inc. All rights reserved. 2 | " 3 | " Licensed under the Apache License, Version 2.0 (the "License"); 4 | " you may not use this file except in compliance with the License. 5 | " You may obtain a copy of the License at 6 | " 7 | " http://www.apache.org/licenses/LICENSE-2.0 8 | " 9 | " Unless required by applicable law or agreed to in writing, software 10 | " distributed under the License is distributed on an "AS IS" BASIS, 11 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | " See the License for the specific language governing permissions and 13 | " limitations under the License. 14 | 15 | "" 16 | " @section Introduction, intro 17 | " @stylized Coverage 18 | " @order intro usage sources plugins packages config commands functions about 19 | " Coverage is a generic vim coverage layer plugin. It depends upon |Maktaba|. 20 | " 21 | " Everybody knows test coverage is important. It is not paramount and you 22 | " should not strive to cover every line, rather to cover sensible usecases, 23 | " but it is still important to spot untested branches and code paths. 24 | " 25 | " Coverage report uses three colors: 26 | " 27 | " * red - line not covered 28 | " * partial - branch taken, but not in all paths 29 | " * green - fully covered 30 | " 31 | " See more about branch coverage on http://en.wikipedia.org/wiki/Code_coverage 32 | 33 | " This plugin offers generic support for rendering code coverage. Coverage 34 | " providers can be registered by other plugins that integrate with |coverage|, 35 | " using |maktaba| for the registration. 36 | 37 | "" 38 | " @section Usage, usage 39 | " 40 | " To use this plugin, you need at least one coverage provider registered with 41 | " it. This plugin provides a generic way to show coverage report line-by-line, 42 | " but it requires a source of the information. Any plugin wishing to be a 43 | " coverage provider needs only to register itself using 44 | " @function(coverage#AddProvider), and pass a |Dictionary| with the following 45 | " |Dictionary-function| defined: 46 | " - IsAvailable(filename) - return 1 if plugin can handle the current file, 47 | " otherwise 0. 48 | " - GetCoverage(filename) - returns the coverage dict created by 49 | " @function(coverage#CreateReport) that contains all coverage data. 50 | " - Name() - returns the name of the plugin. 51 | " - optional: GetCoverageAsync(filename, callback) - gets the coverage and 52 | " once done, invokes the provided callback with the coverage dict created by 53 | " @function(coverage#CreateReport) that contains all coverage data. 54 | " 55 | " You can define a mapping to toggle showing coverage report. To use the default 56 | " mapping of "Ct", add the following to your vimrc: 57 | " > 58 | " Glaive coverage plugin[mappings] 59 | " < 60 | 61 | scriptencoding utf-8 62 | 63 | let [s:plugin, s:enter] = maktaba#plugin#Enter(expand(':p')) 64 | if !s:enter 65 | finish 66 | endif 67 | 68 | "" 69 | " Text shown on the sign of a partially-covered line (e.g. unexplored branch). 70 | call s:plugin.Flag('partial_text', '◊◊') 71 | 72 | "" 73 | " Text shown on the sign of a noncovered line (left of the line, in the corner). 74 | call s:plugin.Flag('uncovered_text', '▵▵') 75 | 76 | "" 77 | " Text shown on the sign of a covered line (left of the line, in the corner). 78 | call s:plugin.Flag('covered_text', '▴▴') 79 | 80 | "" 81 | " Background color for the partially covered lines when in cterm mode (non-GUI). 82 | call s:plugin.Flag('partial_ctermbg', 'yellow') 83 | 84 | "" 85 | " Text color for the partially covered lines when in cterm mode (non-GUI). 86 | call s:plugin.Flag('partial_ctermfg', 'black') 87 | 88 | "" 89 | " Background color for the partially covered lines when in GUI mode (e.g. gvim). 90 | call s:plugin.Flag('partial_guibg', 'yellow') 91 | 92 | "" 93 | " Text color for the partially covered lines when in GUI mode (e.g. gvim). 94 | call s:plugin.Flag('partial_guifg', 'black') 95 | 96 | "" 97 | " Background color for the covered lines when in cterm mode (non-GUI). 98 | call s:plugin.Flag('covered_ctermbg', 'lightgreen') 99 | 100 | "" 101 | " Text color for the covered lines when in cterm mode (non-GUI). 102 | call s:plugin.Flag('covered_ctermfg', 'black') 103 | 104 | "" 105 | " Background color for the covered lines when in GUI mode (e.g. gvim). 106 | call s:plugin.Flag('covered_guibg', 'green') 107 | 108 | "" 109 | " Text color for the covered lines when in GUI mode (e.g. gvim). 110 | call s:plugin.Flag('covered_guifg', 'black') 111 | 112 | "" 113 | " Background color for the uncovered lines when in cterm mode (non-GUI). 114 | call s:plugin.Flag('uncovered_ctermbg', 'red') 115 | 116 | "" 117 | " Text color for the uncovered lines when in cterm mode (non-GUI). 118 | call s:plugin.Flag('uncovered_ctermfg', 'white') 119 | 120 | "" 121 | " Background color for the uncovered lines when in GUI mode (e.g. gvim). 122 | call s:plugin.Flag('uncovered_guibg', 'red') 123 | 124 | "" 125 | " Text color for the uncovered lines when in GUI mode (e.g. gvim). 126 | call s:plugin.Flag('uncovered_guifg', 'white') 127 | -------------------------------------------------------------------------------- /plugin/commands.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2014 Google Inc. All rights reserved. 2 | " 3 | " Licensed under the Apache License, Version 2.0 (the "License"); 4 | " you may not use this file except in compliance with the License. 5 | " You may obtain a copy of the License at 6 | " 7 | " http://www.apache.org/licenses/LICENSE-2.0 8 | " 9 | " Unless required by applicable law or agreed to in writing, software 10 | " distributed under the License is distributed on an "AS IS" BASIS, 11 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | " See the License for the specific language governing permissions and 13 | " limitations under the License. 14 | 15 | let [s:plugin, s:enter] = maktaba#plugin#Enter(expand(':p')) 16 | if !s:enter 17 | finish 18 | endif 19 | 20 | "" 21 | " Show coverage report. If variable b:coverage_provider is set, the provider 22 | " from it will be used. Add a bang (CoverageShow!) to ignore the cache. 23 | command -nargs=* -bang -complete=customlist,coverage#CompletionList CoverageShow 24 | \ call coverage#Show(0, ) 25 | 26 | "" 27 | " Toggle coverage report. Add a bang (CoverageToggle!) to ignore the cache. 28 | command -nargs=0 -bang CoverageToggle call coverage#Toggle(0) 29 | 30 | "" 31 | " Show coverage report when the file changed, using vimdiff. 32 | command -nargs=0 CoverageShowDiff call coverage#ShowDiff() 33 | 34 | "" 35 | " Hide coverage report. 36 | command -nargs=0 CoverageHide call coverage#Hide() 37 | 38 | "" 39 | " Print formatted stats, e.g. Coverage 88% (22/25 lines). 40 | command -nargs=0 CoverageStats echomsg coverage#GetFormattedStats(expand('%:p')) 41 | -------------------------------------------------------------------------------- /plugin/coverage.vim: -------------------------------------------------------------------------------- 1 | let [s:plugin, s:enter] = maktaba#plugin#Enter(expand(':p')) 2 | if !s:enter 3 | finish 4 | endif 5 | 6 | 7 | " Require maktaba 1.12.0 or later for maktaba#python#Eval support. 8 | if !maktaba#IsAtLeastVersion('1.12.0') 9 | call maktaba#error#Shout('Coverage requires maktaba version 1.12.0.') 10 | call maktaba#error#Shout('You have maktaba version %s.', maktaba#VERSION) 11 | call maktaba#error#Shout('Please update your maktaba install.') 12 | endif 13 | 14 | 15 | let s:registry = s:plugin.GetExtensionRegistry() 16 | call s:registry.SetValidator('coverage#EnsureProvider') 17 | 18 | call s:registry.AddExtension(coverage#python#GetCoveragePyProvider()) 19 | call s:registry.AddExtension(coverage#vim#GetCovimerageProvider()) 20 | call s:registry.AddExtension(coverage#gcov#GetGcovProvider()) 21 | -------------------------------------------------------------------------------- /plugin/mappings.vim: -------------------------------------------------------------------------------- 1 | " Copyright 2014 Google Inc. All rights reserved. 2 | " 3 | " Licensed under the Apache License, Version 2.0 (the "License"); 4 | " you may not use this file except in compliance with the License. 5 | " You may obtain a copy of the License at 6 | " 7 | " http://www.apache.org/licenses/LICENSE-2.0 8 | " 9 | " Unless required by applicable law or agreed to in writing, software 10 | " distributed under the License is distributed on an "AS IS" BASIS, 11 | " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | " See the License for the specific language governing permissions and 13 | " limitations under the License. 14 | 15 | "" 16 | " @section Commands, commands 17 | " For toggling coverage view, the t mapping is set. To automatically 18 | " render coverage for available file types, create an autocmd, e.g.: > 19 | " augroup coverage 20 | " autocmd! 21 | " autocmd BufReadPost *.py,*.c,*.cc,*.h,*.java,*.go,*.js :CoverageShow 22 | " augroup END 23 | " < 24 | " 25 | " This will render coverage for all mentioned filetypes, if available. 26 | 27 | let [s:plugin, s:enter] = maktaba#plugin#Enter(expand(':p')) 28 | if !s:enter 29 | finish 30 | endif 31 | 32 | let s:prefix = s:plugin.MapPrefix('C') 33 | execute 'nnoremap