├── .clang_complete
├── .coveragerc
├── .github
├── CONTRIBUTING.md
├── FUNDING.yml
├── ISSUE_TEMPLATE.md
├── PULL_REQUEST_TEMPLATE.md
├── no-response.yml
├── stale.yml
└── workflows
│ └── main.yml
├── .gitignore
├── .no-sublime-package
├── Default.sublime-commands
├── Default.sublime-keymap
├── EasyClangComplete.py
├── EasyClangComplete.sublime-settings
├── LICENSE
├── Main.sublime-menu
├── Preferences.sublime-settings
├── README.md
├── dependencies.json
├── docs
├── about.md
├── commands.md
├── configs.md
├── credits.md
├── img
│ ├── AutoComplete.gif
│ ├── ecc.png
│ ├── error.png
│ ├── error_dot.png
│ ├── error_mono.png
│ ├── favicon.ico
│ ├── includes.gif
│ ├── my_photo.jpg
│ ├── warning.png
│ ├── warning_dot.png
│ └── warning_mono.png
├── includes_completion.md
├── index.md
├── pc_readme.md
├── settings.md
└── support.md
├── easy_clang_complete.sublime-project
├── external
└── bazel-compilation-database
│ ├── .ycm_extra_conf.py
│ ├── BUILD
│ ├── LICENSE
│ ├── README.md
│ ├── WORKSPACE
│ ├── aspects.bzl
│ ├── generate.sh
│ └── plugin
│ └── bazel-compilation-database.vim
├── messages.json
├── messages
├── 2.0.0.rst
├── 3.0.0.rst
├── 4.0.0.rst
├── 5.0.0.rst
├── 6.0.0.rst
├── 6.0.1.rst
├── 6.0.2.rst
├── 6.0.3.rst
├── 6.1.0.rst
├── 6.1.1.rst
├── 6.1.2.rst
├── 6.1.3.rst
├── 6.2.0.rst
├── 6.2.1.rst
├── 6.2.2.rst
├── 6.2.3.rst
├── 6.2.4.rst
├── 6.2.5.rst
├── 6.2.6.rst
├── 6.2.7.rst
├── 6.2.8.rst
├── 6.3.0.rst
├── 6.4.0.rst
├── 6.4.1.rst
├── 6.4.2.rst
├── 6.4.3.rst
├── 6.4.4.rst
├── 6.4.5.rst
├── 6.5.0.rst
├── 6.5.1.rst
├── 6.5.2.rst
└── install.rst
├── mkdocs.yml
├── pics
├── ecc.png
└── icons
│ ├── dot.svg
│ ├── error.png
│ ├── error.svg
│ ├── error_dot.png
│ ├── error_mono.png
│ ├── warning.png
│ ├── warning.svg
│ ├── warning_dot.png
│ └── warning_mono.png
├── plugin
├── __init__.py
├── clang
│ ├── __init__.py
│ ├── cindex.py
│ ├── cindex32.py
│ ├── cindex33.py
│ ├── cindex34.py
│ ├── cindex35.py
│ ├── cindex36.py
│ ├── cindex37.py
│ ├── cindex38.py
│ ├── cindex39.py
│ ├── cindex40.py
│ ├── cindex50.py
│ └── enumerations.py
├── completion
│ ├── __init__.py
│ ├── base_complete.py
│ ├── bin_complete.py
│ ├── compiler_variant.py
│ └── lib_complete.py
├── error_vis
│ ├── __init__.py
│ ├── popup.css
│ ├── popup_error_vis.py
│ └── popups.py
├── flags_sources
│ ├── CppProperties.py
│ ├── __init__.py
│ ├── bazel.py
│ ├── c_cpp_properties.py
│ ├── cmake_file.py
│ ├── compilation_db.py
│ ├── compiler_builtins.py
│ ├── flags_file.py
│ ├── flags_source.py
│ └── makefile.py
├── settings
│ ├── __init__.py
│ ├── settings_manager.py
│ └── settings_storage.py
├── utils
│ ├── __init__.py
│ ├── action_request.py
│ ├── catkinizer.py
│ ├── clang_utils.py
│ ├── file.py
│ ├── flag.py
│ ├── include_parser.py
│ ├── index_location.py
│ ├── macro_parser.py
│ ├── module_reloader.py
│ ├── output_panel_handler.py
│ ├── progress_status.py
│ ├── quick_panel_handler.py
│ ├── search_scope.py
│ ├── singleton.py
│ ├── subl
│ │ ├── row_col.py
│ │ └── subl_bridge.py
│ ├── thread_job.py
│ ├── thread_pool.py
│ ├── tools.py
│ └── unique_list.py
└── view_config
│ ├── __init__.py
│ ├── view_config.py
│ └── view_config_manager.py
├── tests
├── CppProperties_files
│ ├── empty
│ │ └── CppProperties.json
│ ├── environment
│ │ └── CppProperties.json
│ └── simple
│ │ └── CppProperties.json
├── __init__.py
├── bazel
│ ├── bad_project
│ │ ├── WORKSPACE
│ │ └── app
│ │ │ ├── BUILD
│ │ │ └── main.cpp
│ └── good_project
│ │ ├── WORKSPACE
│ │ └── app
│ │ ├── BUILD
│ │ └── main.cpp
├── c_cpp_properties_files
│ ├── c_cpp_properties.json
│ ├── empty
│ │ └── c_cpp_properties.json
│ ├── environment
│ │ └── c_cpp_properties.json
│ └── simple
│ │ └── c_cpp_properties.json
├── catkin_tests
│ └── catkin_ws
│ │ └── src
│ │ └── project
│ │ ├── CMakeLists.txt
│ │ └── main.cpp
├── cmake_tests
│ ├── CMakeLists.txt
│ ├── lib
│ │ ├── CMakeLists.txt
│ │ ├── a.cpp
│ │ └── a.h
│ └── test_a.cpp
├── compilation_db_files
│ ├── arguments
│ │ └── compile_commands.json
│ ├── command
│ │ └── compile_commands.json
│ ├── command_c
│ │ └── compile_commands.json
│ ├── command_c_ccache
│ │ └── compile_commands.json
│ ├── command_c_ccache_irrelevant
│ │ └── compile_commands.json
│ └── directory
│ │ └── compile_commands.json
├── gui_test_wrapper.py
├── makefile_files
│ ├── .gitignore
│ ├── Makefile
│ ├── inc
│ │ └── bar.h
│ ├── lib
│ │ ├── Makefile
│ │ ├── bar.c
│ │ └── foo
│ │ │ ├── foo.c
│ │ │ └── foo.h
│ └── main.c
├── test_CppProperties.py
├── test_action_request.py
├── test_bazel.py
├── test_c_cpp_properties.py
├── test_catkinizer.py
├── test_clang_complete_file.py
├── test_clang_utils.py
├── test_cmake_file.py
├── test_compilation_db.py
├── test_compiler_builtins.py
├── test_complete.py
├── test_docs.py
├── test_error_vis.py
├── test_file.py
├── test_files
│ ├── Makefile.cmake
│ ├── test.cpp
│ ├── testTemplatesManual.cpp
│ ├── test_changes.cpp
│ ├── test_errors.cpp
│ ├── test_info.cpp
│ ├── test_info_arguments_link.cpp
│ ├── test_location.cpp
│ ├── test_method_one_parameter.m
│ ├── test_method_two_parameters.m
│ ├── test_objective_c.m
│ ├── test_objective_c_covariant.m
│ ├── test_objective_cpp.mm
│ ├── test_property.m
│ ├── test_templates.cpp
│ ├── test_unicode.cpp
│ ├── test_vector.cpp
│ ├── test_void_method.m
│ └── test_wrong_triggers.cpp
├── test_flag.py
├── test_flags_source.py
├── test_include_parser.py
├── test_index_location.py
├── test_macro_parser.py
├── test_makefile.py
├── test_output_panel_handler.py
├── test_panel_handler.py
├── test_row_col.py
├── test_search_scope.py
├── test_settings.py
├── test_singleton.py
├── test_style.py
├── test_subl_bridge.py
├── test_thread_pool.py
├── test_tools.py
├── test_unique_list.py
└── test_view_config.py
└── unittesting.json
/.clang_complete:
--------------------------------------------------------------------------------
1 | -I/home/igor/.config/sublime-text-3/Packages/EasyClangComplete/src blah
2 | -I/home/igor/.config/sublime-text-3/Packages/EasyClangComplete
3 | -Ilocal_folder
4 | -Wabi
5 | -std=c++14
6 |
--------------------------------------------------------------------------------
/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | omit =
3 | /*/tests/*
4 | /*/clang/*
5 | /*/EasyClangComplete.py
6 |
7 | [report]
8 | ignore_errors = True
9 |
10 | [xml]
11 | output = .cobertura
12 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing ##
2 | Contributions are welcome! Look at the issue list. If there is something you
3 | think you can tackle, write about it in that issue and submit a Pull Request.
4 |
5 | ### Follow issue template! ###
6 | Please follow the issue template *exactly* when creating a new issue.
7 | I will be closing issues that do not follow that template. Please understand
8 | that maintaining this codebase takes time and I expect at least well-formatted
9 | issue statement to be able to tackle it. It is very demotivating to format
10 | the issues instead of actually solving them, so I would really like to outsource this task to the original submitter.
11 |
12 | Please don't jump into creating a Pull Request straight away and open an issue
13 | first. This way, we can synchronize our views on the problem, so that everyone
14 | avoids losing time.
15 |
16 | ### Branches ###
17 | There are two branches:
18 | - `master`: used for ongoing development. Merges into `release` branchright
19 | before a new release.
20 | - `release`: should be stable and following the last release. Used for urgent
21 | bug fixing exclusively on top of the previous release.
22 |
23 | ### Code style ###
24 | - Line width is `80` characters
25 | - Every public function should be documented.
26 | - The code *must* pass linters:
27 | + `pep8`
28 | + `pep257`: ignoring `["D209", "D203", "D204", "D213", "D406", "D407"]`
29 |
30 | Please ensure, that your code conforms to this.
31 |
32 | ## Tests ##
33 | Most crucial functionality is covered with unit tests using
34 | [UnitTesting](https://github.com/randy3k/UnitTesting) Sublime Text plugin.
35 |
36 | Whenever you contribute new functionality, please make sure it is covered
37 | by unit tests. It helps to maintain the quality of this software and to
38 | deal with all complex parts. I will not merge the PRs without unit tests
39 | covering the new functionality.
40 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: niosus
4 | open_collective: niosus
5 | issuehunt: niosus
6 | custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2QLY7J4Q944HS']
7 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | # Read instructions carefully! #
2 | - I know its annoying, but bear with me
3 | - Take 2 minutes to make sure your issue is readable
4 | - I will close malformed issues
5 |
6 | # Please do this before submitting: #
7 | - Check for already solved issues
8 | - Try restarting Sublime Text
9 | - Remove this header and fill info below the line
10 |
11 | # Create minimal example if you can #
12 | If you can create a minimal example and link it here.
13 | - Ideally it should compile on Linux
14 | - It must work if I build it from the terminal
15 |
16 | # Copy the log #
17 | To capture the log:
18 | - Set `"verbose": true` in plugin settings
19 | - Restart Sublime Text
20 | - Open the file or do the action that causes trouble
21 | - Open console with Ctrl+`
22 | - Copy *full* output to a text file and link it to this issue
23 | - Or copy it below under ``
24 |
25 | # Fill the gaps below this line and remove all text above it #
26 | --------------------------------------------------------------
27 |
28 | # System info: #
29 | - Sublime Text version: ``
30 | - Which system are you on: ``
31 | - Clang version: ``
32 |
33 | # What happens: #
34 | Describe your issue here.
35 |
36 |
37 | Log that illustrates the issue:
38 |
39 | ```
40 |
41 | ```
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | # Before submitting make sure #
2 | - Make sure your branch is based on `master`
3 | - Reference an issue that this PR closes if there is one
4 | - Add your PR descriptions below the line
5 | - Remove this prefix (everything above the line right below)
6 |
7 | -------------------------------------------------------------------------------
8 |
9 | YOUR PR DESCRIPTION GOES HERE
10 |
11 |
--------------------------------------------------------------------------------
/.github/no-response.yml:
--------------------------------------------------------------------------------
1 | # Configuration for probot-no-response - https://github.com/probot/no-response
2 |
3 | # Number of days of inactivity before an Issue is closed for lack of response
4 | daysUntilClose: 30
5 | # Label requiring a response
6 | responseRequiredLabel: awaiting-feedback
7 | # Comment to post when closing an Issue for lack of response. Set to `false` to disable
8 | closeComment: >
9 | This issue has been automatically closed because there has been no response
10 | to our request for more information from the original author. With only the
11 | information that is currently in the issue, we don't have enough information
12 | to take action. Please feel free to reopen with more information.
13 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 365
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 30
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - pinned
8 | - security
9 | # Label to use when marking an issue as stale
10 | staleLabel: wontfix
11 | # Comment to post when marking an issue as stale. Set to `false` to disable
12 | markComment: >
13 | This issue has been automatically marked as stale because it has not had
14 | recent activity. It will be closed if no further activity occurs. Just comment
15 | here to prevent this from happening.
16 | # Comment to post when closing a stale issue. Set to `false` to disable
17 | closeComment: >
18 | The issue has been automatically closed due to lack of activity. Feel free to
19 | reopen the issue if it is still relevant.
20 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: test
2 |
3 | on: [pull_request]
4 |
5 | jobs:
6 | run-tests:
7 | strategy:
8 | fail-fast: false
9 | matrix:
10 | st-version: [4]
11 | os: ["ubuntu-latest", "macOS-latest", "windows-latest"]
12 | runs-on: ${{ matrix.os }}
13 | steps:
14 | - uses: actions/checkout@v2
15 | - uses: SublimeText/UnitTesting/actions/setup@v1
16 | with:
17 | sublime-text-version: ${{ matrix.st-version }}
18 | - name: Install dependencies
19 | if: runner.os == 'Linux'
20 | run: |
21 | python -m pip install --upgrade pip pycodestyle pep257 mkdocs mkdocs-material
22 | curl -L -o bazelisk "https://github.com/bazelbuild/bazelisk/releases/download/v1.3.0/bazelisk-linux-amd64"
23 | chmod +x bazelisk && sudo mv bazelisk /usr/local/bin/bazel
24 | shell: bash
25 | - uses: SublimeText/UnitTesting/actions/run-tests@v1
26 | with:
27 | coverage: true
28 | codecov-upload: true
29 | - name: Build mkdocs
30 | if: runner.os == 'Linux'
31 | run: mkdocs build --verbose --clean --strict;
32 | - name: Deploy to GitHub Pages
33 | if: runner.os == 'Linux' && github.ref == 'refs/heads/master'
34 | uses: JamesIves/github-pages-deploy-action@4.1.7
35 | with:
36 | branch: gh-pages
37 | folder: site
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # added by GitSavvy
3 | /easy_clang_complete.sublime-workspace
4 |
5 | # added by GitSavvy
6 | /test.c
7 |
8 | # added by GitSavvy
9 | /test.cpp
10 |
11 | # added by GitSavvy
12 | /easy_auto_complete.sublime-workspace
13 |
14 | # added by GitSavvy
15 | /tests/cmake_tests/.clang_complete
16 |
17 | /plugin/utils/__pycache__/
18 |
19 | *__pycache__/
20 | EasyClangComplete.sublime-workspace
21 |
22 | *.pyc
23 |
24 | /docs/.sass-cache/
25 |
26 | /site/
27 | /tests/bazel_project/bazel-bazel_project
28 | /tests/bazel_project/bazel-bin
29 | /tests/bazel_project/bazel-out
30 | /tests/bazel_project/bazel-testlogs
31 | /tests/bazel_project/compile_commands.json
32 | tests/bazel/good_project/bazel-*
33 | *compile_commands.json
34 | tests/bazel/bad_project/bazel-*
35 |
--------------------------------------------------------------------------------
/.no-sublime-package:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/.no-sublime-package
--------------------------------------------------------------------------------
/Default.sublime-commands:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "caption": "ECC: Settings",
4 | "command": "edit_settings",
5 | "args": {
6 | "base_file": "${packages}/EasyClangComplete/EasyClangComplete.sublime-settings"
7 | }
8 | },
9 | {
10 | "caption": "ECC: Open completion triggers location",
11 | "command": "edit_settings",
12 | "args": {
13 | "base_file": "${packages}/EasyClangComplete/Preferences.sublime-settings"
14 | }
15 | },
16 | {
17 | "caption": "ECC: Show all errors",
18 | "command": "ecc_show_all_errors"
19 | },
20 | {
21 | "caption": "ECC: Clean current CMake cache",
22 | "command": "clean_cmake"
23 | },
24 | {
25 | "caption": "ECC: Show popup info",
26 | "command": "ecc_show_popup_info"
27 | },
28 | {
29 | "caption": "ECC: (Bazel) Generate compile_commands.json",
30 | "command": "generate_bazel_comp_db"
31 | },
32 | ]
33 |
--------------------------------------------------------------------------------
/Default.sublime-keymap:
--------------------------------------------------------------------------------
1 | [
2 | { "keys": ["shift+f12"], "command": "ecc_goto_declaration"},
3 | {
4 | "keys": ["<"],
5 | "command": "ecc_complete_includes",
6 | "args": {"opening_char": "<"},
7 | "context":
8 | [
9 | {"key": "selector", "operand": "meta.preprocessor.include"},
10 | {"key": "auto_complete_visible", "operand": false }
11 | ]
12 | },
13 | {
14 | "keys": ["\""],
15 | "command": "ecc_complete_includes",
16 | "args": {"opening_char": "\""},
17 | "context":
18 | [
19 | {"key": "selector", "operand": "meta.preprocessor.include"},
20 | {"key": "auto_complete_visible", "operand": false }
21 | ]
22 | }
23 | ]
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2018 Igor Bogoslavskyi
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9 |
--------------------------------------------------------------------------------
/Main.sublime-menu:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "caption": "Preferences",
4 | "mnemonic": "n",
5 | "id": "preferences",
6 | "children":
7 | [
8 | {
9 | "caption": "Package Settings",
10 | "mnemonic": "P",
11 | "id": "package-settings",
12 | "children":
13 | [
14 | {
15 | "caption": "EasyClangComplete",
16 | "children":
17 | [
18 | {
19 | "command": "edit_settings",
20 | "args":
21 | {
22 | "base_file": "${packages}/EasyClangComplete/EasyClangComplete.sublime-settings"
23 | },
24 | "caption": "Settings"
25 | },
26 |
27 | {
28 | "command": "edit_settings",
29 | "args": {
30 | "base_file": "${packages}/EasyClangComplete/Default ($platform).sublime-keymap"
31 | },
32 | "caption": "Key Bindings"
33 | },
34 | ]
35 | }
36 | ]
37 | }
38 | ]
39 | }
40 | ]
41 |
--------------------------------------------------------------------------------
/Preferences.sublime-settings:
--------------------------------------------------------------------------------
1 | {
2 | // DO NOT MODIFY!
3 | // Your changes will be overwritten upon plugin update.
4 | // To change the triggers, copy these lines to your user preferences.
5 | "auto_complete_triggers":
6 | [
7 | {
8 | "selector": "source.c++ - string - comment - constant.numeric",
9 | "characters": ".>:",
10 | },
11 | {
12 | "selector": "source.c - string - comment - constant.numeric",
13 | "characters": ".>:",
14 | },
15 | {
16 | "selector": "source.objc++ - string - comment - constant.numeric",
17 | "characters": ".>: ",
18 | },
19 | {
20 | "selector": "source.objc - string - comment - constant.numeric",
21 | "characters": ".>: ",
22 | },
23 | {
24 | "selector": "source.cuda-c++ - string - comment - constant.numeric",
25 | "characters": ".>: ",
26 | },
27 | ],
28 | }
29 |
--------------------------------------------------------------------------------
/dependencies.json:
--------------------------------------------------------------------------------
1 | {
2 | "*": {
3 | ">=3124": [
4 | "pygments",
5 | "python-markdown",
6 | "mdpopups",
7 | "python-jinja2",
8 | "markupsafe",
9 | "pymdownx",
10 | "pyyaml"
11 | ]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/docs/about.md:
--------------------------------------------------------------------------------
1 | # About me
2 |
3 | 
4 |
5 | I started this plugin as a PhD student at the University of Bonn, doing
6 | Robotics, Computer Vision and Photogrammetry. I wrote this plugin because
7 | of my obsession with Sublime Text and the need (and will) to code in C++ every
8 | day. At the start of this journey there was no plugin that would suit my needs *exactly* and as a result you see this plugin here today.
9 |
10 | ## [Support the development of this plugin](support.md)
11 |
--------------------------------------------------------------------------------
/docs/commands.md:
--------------------------------------------------------------------------------
1 | # Available commands
2 | There is a number of commands that you can run from Sublime Text with
3 | Ctrl+Shift+P (or
4 | Cmd+Shift+P on MacOS) that are related to
5 | EasyClangComplete.
6 |
7 | !!! tip "Pro tip"
8 | You can assign a key binding to any of the commands represented below to make running them quick and effortless.
9 |
10 | ## Clear CMake cache
11 | Ctrl+Shift+P -> `Clean current CMake cache`
12 |
13 | This command makes sure we clean the temporary build folder where CMake
14 | generates files.
15 |
16 | ## Show all errors
17 | Ctrl+Shift+P -> `Show all errors`
18 |
19 | This command shows a panel with a list of all errors that are visible from the current translation unit. When you select one, the plugin will navigate you to the place where the error occurs.
20 |
21 | ## Show popup info
22 | Ctrl+Shift+P -> `Show popup info`
23 |
24 | Show an information popup with the type of the symbol under the cursor.
25 |
26 | ## Open settings
27 | Ctrl+Shift+P -> `Settings`
28 |
29 | Open a new window with **Default** and **User** settings opened side by side for quick adjustment of the settings used by the plugin.
30 |
31 | ## Generate a compilation database with Bazel
32 | Ctrl+Shift+P -> `Generate compile_commands.json`
33 |
34 | Uses Bazel through the script provided by [@grailbio](https://github.com/grailbio/bazel-compilation-database) to generate a `compile_commands.json` file in the folder of your `WORKSPACE` file. By default, the plugin will then be able to read this file to get the correct flags.
35 |
36 |
--------------------------------------------------------------------------------
/docs/credits.md:
--------------------------------------------------------------------------------
1 | # Credits
2 | The whole work seen here was originally a fork of another repository:
3 | [ClangAutoComplete](https://github.com/pl-ca/ClangAutoComplete)
4 |
5 | However, with time this plugin has grown quite different from its origin and
6 | this is why you see it as a separate package now. Anyway, feel free to check
7 | out what `ClangAutoComplete` has to offer and come back if you still like this
8 | plugin more.
9 |
10 | The trick with multiple `clang.cindex` files is inspired by this repo:
11 | [clangHelper](https://github.com/griebd/clangHelper). Thanks for inspiration!
12 |
13 | The progress indicator idea is from
14 | [ColorSublime](https://github.com/Colorsublime/Colorsublime-Plugin) plugin.
15 |
16 | Some functionality is there only because of the awesome contributors to this
17 | project. To see their names plese check out the contributors page.
18 |
--------------------------------------------------------------------------------
/docs/img/AutoComplete.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/docs/img/AutoComplete.gif
--------------------------------------------------------------------------------
/docs/img/ecc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/docs/img/ecc.png
--------------------------------------------------------------------------------
/docs/img/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/docs/img/error.png
--------------------------------------------------------------------------------
/docs/img/error_dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/docs/img/error_dot.png
--------------------------------------------------------------------------------
/docs/img/error_mono.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/docs/img/error_mono.png
--------------------------------------------------------------------------------
/docs/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/docs/img/favicon.ico
--------------------------------------------------------------------------------
/docs/img/includes.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/docs/img/includes.gif
--------------------------------------------------------------------------------
/docs/img/my_photo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/docs/img/my_photo.jpg
--------------------------------------------------------------------------------
/docs/img/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/docs/img/warning.png
--------------------------------------------------------------------------------
/docs/img/warning_dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/docs/img/warning_dot.png
--------------------------------------------------------------------------------
/docs/img/warning_mono.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/docs/img/warning_mono.png
--------------------------------------------------------------------------------
/docs/includes_completion.md:
--------------------------------------------------------------------------------
1 | # Completing the includes (exprerimental)
2 |
3 | The plugin has an experimental capability to complete includes. Currently, the automatic completion after typing `#include <` will not work due to a way brackets get auto-matched by Sublime Text (read more about it [here](https://forum.sublimetext.com/t/completion-triggers/13139/5)).
4 |
5 | However, when using Alt+/ on Linux and Ctrl+Space on Windows and macOS after `<` symbol while typing `#include <` the plugin will walk the tree starting at the current include folders (read more about where these come from [here](../configs)) to generate a list of potential includes that it will show momentarily.
6 |
7 | This is still experimental and can be a bit slow. Also, the number of includes is limited by approx. 4 million entries.
8 |
--------------------------------------------------------------------------------
/docs/pc_readme.md:
--------------------------------------------------------------------------------
1 | # EasyClangComplete auto-completion for human beings
2 |
3 | 
4 |
5 | ## **Simple start in just 3 steps!**
6 |
7 | ### **1. Install this plugin**
8 |
9 | - In Sublime Text press CTRL+Shift+P and
10 | install `EasyClangComplete`
11 |
12 | ### **2. Install clang**
13 | - **Ubuntu** : `sudo apt-get install clang`
14 | - **OSX** : ships `clang` by default. You are all set!
15 | - **Windows** : install the latest release from clang website.
16 | - **Other Systems** : use your package manager or install from clang website.
17 | - clang website: http://llvm.org/releases/download.html
18 |
19 | ### **3. Configure your compiler flags and include folders**
20 |
21 | #### Do you use CMake?
22 | You're in luck! The plugin will run cmake on a proper `CMakeLists.txt` in your
23 | project folder and will use information from it to complete your code out of
24 | the box! For more details, read the plugin docs about
25 | [CMake](https://niosus.github.io/EasyClangComplete/configs/#using-cmake-recommended).
26 |
27 | #### Don't like CMake?
28 | Don't worry! There are plenty of ways to configure the plugin! Read the related
29 | documentation [page](https://niosus.github.io/EasyClangComplete/configs/) for
30 | more info!
31 |
32 | ## [Extensive documentation](https://niosus.github.io/EasyClangComplete/)
33 | There are so many things I want to tell you! There is so much the plugin is
34 | capable of! Read the [docs](https://niosus.github.io/EasyClangComplete/) to get
35 | started!
36 |
37 | ## [Support this project!](https://niosus.github.io/EasyClangComplete/support/)
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/docs/support.md:
--------------------------------------------------------------------------------
1 | # Support the project
2 | [![Donate][img-paypal]][donate-paypal]
3 | [![Bountysource][img-bountysource]][bountysource-link]
4 | [![Beerpay][img-beerpay]][beerpay]
5 | [![OpenCollective Backers][img-open-backers]][opencollective]
6 | [![OpenCollective Sponsors][img-open-sponsors]][opencollective]
7 |
8 | This project cost me a ton of sleepless nights. Liters of tea and coke have
9 | been consumed while writing this code. If you feel like this unhealthy behavior
10 | is something you might want to support - smash one of the buttons above (or
11 | below)! You're awesome! :+1:
12 |
13 |
14 |
15 | ## Become a contributor!
16 | Want to support the development and make me sleep even less? Submit a PR or throw some money at me. Your avatar will magically appear below!
17 |
18 |
19 |
20 | ## Become a sponsor!
21 | Are you using this plugin at work at a company? Fight your manager/boss to
22 | support the development of this plugin as it will totally make you so much more
23 | productive :wink:! Plus your company avatar will appear on the main page so
24 | that they can boast that they support Open Source! Imagine how good you and
25 | your company will feel afterwards! :smile:
26 |
27 |
28 |
29 |
30 | [release]: https://github.com/niosus/EasyClangComplete/releases
31 | [downloads]: https://packagecontrol.io/packages/EasyClangComplete
32 | [travis]: https://travis-ci.org/niosus/EasyClangComplete
33 | [appveyor]: https://ci.appveyor.com/project/niosus/easyclangcomplete/branch/master
34 | [codacy]: https://www.codacy.com/app/zabugr/EasyClangComplete/dashboard
35 | [coverage]: https://www.codacy.com/app/zabugr/EasyClangComplete/dashboard
36 | [gitter]: https://gitter.im/niosus/EasyClangComplete?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
37 | [donate-paypal]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2QLY7J4Q944HS
38 | [donate-flattr]: https://flattr.com/submit/auto?user_id=niosus&url=https://github.com/niosus/EasyClangComplete&title=EasyClangComplete&language=Python&tags=github&category=software
39 | [libclang-issue]: https://github.com/niosus/EasyClangComplete/issues/88
40 | [cmake-issue]: https://github.com/niosus/EasyClangComplete/issues/19
41 | [bountysource-link]: https://www.bountysource.com/teams/easyclangcomplete
42 | [beerpay]: https://beerpay.io/niosus/EasyClangComplete
43 | [gratipay]: https://gratipay.com/EasyClangComplete/
44 | [maintainerd]: https://github.com/divmain/maintainerd
45 | [opencollective]: https://opencollective.com/easyclangcomplete/#contributors
46 |
47 | [img-gratipay]: https://img.shields.io/gratipay/user/niosus.svg?style=flat-square
48 | [img-beerpay]: https://beerpay.io/niosus/EasyClangComplete/badge.svg?style=flat-square
49 | [img-bountysource]: https://img.shields.io/bountysource/team/easyclangcomplete/activity.svg?style=flat-square
50 | [img-appveyor]: https://img.shields.io/appveyor/ci/niosus/easyclangcomplete/master.svg?style=flat-square&label=windows
51 | [img-travis]: https://img.shields.io/travis/niosus/EasyClangComplete/master.svg?style=flat-square&label=linux%20|%20osx
52 | [img-codacy]: https://img.shields.io/codacy/grade/254f8db44b004dffa76b8cebfece4c06.svg?style=flat-square
53 | [img-coverage]: https://img.shields.io/codacy/coverage/254f8db44b004dffa76b8cebfece4c06.svg?style=flat-square
54 | [img-release]: https://img.shields.io/github/release/niosus/EasyClangComplete.svg?style=flat-square
55 | [img-downloads]: https://img.shields.io/packagecontrol/dm/EasyClangComplete.svg?maxAge=3600&style=flat-square
56 | [img-downloads-month]: https://img.shields.io/packagecontrol/dm/EasyClangComplete.svg?maxAge=2592000&style=flat-square
57 | [img-subl]: https://img.shields.io/badge/Sublime%20Text-3-green.svg?style=flat-square
58 | [img-mit]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
59 | [img-paypal]: https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square
60 | [img-flattr]: https://img.shields.io/badge/Donate-Flattr-blue.svg?style=flat-square
61 | [img-gitter]: https://badges.gitter.im/niosus/EasyClangComplete.svg?style=flat-square
62 | [img-open-backers]: https://opencollective.com/easyclangcomplete/backers/badge.svg?style=flat-square
63 | [img-open-sponsors]: https://opencollective.com/easyclangcomplete/sponsors/badge.svg?style=flat-square
64 |
--------------------------------------------------------------------------------
/easy_clang_complete.sublime-project:
--------------------------------------------------------------------------------
1 | {
2 | "build_systems":
3 | [
4 | {
5 | "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
6 | "name": "Anaconda Python Builder",
7 | "selector": "source.python",
8 | "shell_cmd": "\"python3\" -u \"$file\""
9 | }
10 | ],
11 | "folders":
12 | [
13 | {
14 | "path": "."
15 | }
16 | ],
17 | "settings":
18 | {
19 | "ecc_flags_sources":
20 | [
21 | {
22 | "file": "CMakeLists.txt",
23 | "flags":
24 | [
25 | "-DCMAKE_BUILD_TYPE=Release",
26 | "-D XXXX=ON"
27 | ],
28 | "prefix_paths":
29 | [
30 | "/opt/ros/indigo",
31 | "~/Code/catkin_ws/devel",
32 | "$project_base_path/catkin_ws/devel"
33 | ]
34 | },
35 | {
36 | "file": "Makefile"
37 | },
38 | {
39 | "file": ".clang_complete"
40 | }
41 | ],
42 | "ecc_use_libclang": true,
43 | "sublack":
44 | {
45 | "black_on_save": false
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/external/bazel-compilation-database/BUILD:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/external/bazel-compilation-database/BUILD
--------------------------------------------------------------------------------
/external/bazel-compilation-database/WORKSPACE:
--------------------------------------------------------------------------------
1 | # Copyright 2017 GRAIL, Inc.
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 | workspace(name = "bazel_compdb")
16 |
17 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
18 |
19 | http_archive(
20 | name = "rules_cc",
21 | urls = ["https://github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.tar.gz"],
22 | sha256 = "3057c13fa4d431eb0e7a9c28eea13f25987d29f869406b5ee3f2bd9c4134cb0c",
23 | )
24 |
--------------------------------------------------------------------------------
/external/bazel-compilation-database/generate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2017 GRAIL, Inc.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # Generates a compile_commands.json file at $(bazel info workspace) for
18 | # libclang based tools.
19 |
20 | # This is inspired from
21 | # https://github.com/google/kythe/blob/master/tools/cpp/generate_compilation_database.sh
22 |
23 | set -e
24 |
25 | source_dir=0
26 |
27 | usage() {
28 | printf "usage: %s flags\nwhere flags can be:\n" "${BASH_SOURCE[0]}"
29 | printf "\t-s\tuse the original source directory instead of bazel execroot\n"
30 | printf "\n"
31 | }
32 |
33 | while getopts "sh" opt; do
34 | case "${opt}" in
35 | "s") source_dir=1 ;;
36 | "h") usage; exit 0;;
37 | *) >&2 echo "invalid option ${opt}"; exit 1;;
38 | esac
39 | done
40 |
41 | # This function is copied from https://source.bazel.build/bazel/+/master:scripts/packages/bazel.sh.
42 | # `readlink -f` that works on OSX too.
43 | function get_realpath() {
44 | if [ "$(uname -s)" == "Darwin" ]; then
45 | local queue="$1"
46 | if [[ "${queue}" != /* ]] ; then
47 | # Make sure we start with an absolute path.
48 | queue="${PWD}/${queue}"
49 | fi
50 | local current=""
51 | while [ -n "${queue}" ]; do
52 | # Removing a trailing /.
53 | queue="${queue#/}"
54 | # Pull the first path segment off of queue.
55 | local segment="${queue%%/*}"
56 | # If this is the last segment.
57 | if [[ "${queue}" != */* ]] ; then
58 | segment="${queue}"
59 | queue=""
60 | else
61 | # Remove that first segment.
62 | queue="${queue#*/}"
63 | fi
64 | local link="${current}/${segment}"
65 | if [ -h "${link}" ] ; then
66 | link="$(readlink "${link}")"
67 | queue="${link}/${queue}"
68 | if [[ "${link}" == /* ]] ; then
69 | current=""
70 | fi
71 | else
72 | current="${link}"
73 | fi
74 | done
75 |
76 | echo "${current}"
77 | else
78 | readlink -f "$1"
79 | fi
80 | }
81 |
82 | readonly ASPECTS_DIR="$(dirname "$(get_realpath "${BASH_SOURCE[0]}")")"
83 | readonly OUTPUT_GROUPS="compdb_files"
84 |
85 | readonly WORKSPACE="$(bazel info workspace)"
86 | readonly EXEC_ROOT="$(bazel info execution_root)"
87 | readonly COMPDB_FILE="${WORKSPACE}/compile_commands.json"
88 |
89 | readonly QUERY_CMD=(
90 | bazel query
91 | --noshow_progress
92 | --noshow_loading_progress
93 | 'kind("cc_(library|binary|test|inc_library|proto_library)", //...) union kind("objc_(library|binary|test)", //...)'
94 | )
95 |
96 | # Clean any previously generated files.
97 | if [[ -e "${EXEC_ROOT}" ]]; then
98 | find "${EXEC_ROOT}" -name '*.compile_commands.json' -delete
99 | fi
100 |
101 | # shellcheck disable=SC2046
102 | bazel build \
103 | "--override_repository=bazel_compdb=${ASPECTS_DIR}" \
104 | "--aspects=@bazel_compdb//:aspects.bzl%compilation_database_aspect" \
105 | "--noshow_progress" \
106 | "--noshow_loading_progress" \
107 | "--output_groups=${OUTPUT_GROUPS}" \
108 | "$@" \
109 | $("${QUERY_CMD[@]}") > /dev/null
110 |
111 | echo "[" > "${COMPDB_FILE}"
112 | find "${EXEC_ROOT}" -name '*.compile_commands.json' -exec bash -c 'cat "$1" && echo ,' _ {} \; \
113 | >> "${COMPDB_FILE}"
114 | echo "]" >> "${COMPDB_FILE}"
115 |
116 | sed -i.bak -e '/^,$/d' -e '$s/,$//' "${COMPDB_FILE}" # Hygiene to make valid json
117 | if (( source_dir )); then
118 | sed -i.bak -e "s|__EXEC_ROOT__|${WORKSPACE}|" "${COMPDB_FILE}" # Replace exec_root marker
119 | # This is for libclang to help find source files from external repositories.
120 | ln -f -s "${EXEC_ROOT}/external" "${WORKSPACE}/external"
121 | else
122 | sed -i.bak -e "s|__EXEC_ROOT__|${EXEC_ROOT}|" "${COMPDB_FILE}" # Replace exec_root marker
123 | # This is for YCM to help find the DB when following generated files.
124 | # The file may be deleted by bazel on the next build.
125 | ln -f -s "${WORKSPACE}/${COMPDB_FILE}" "${EXEC_ROOT}/"
126 | fi
127 | sed -i.bak -e "s|-isysroot __BAZEL_XCODE_SDKROOT__||" "${COMPDB_FILE}" # Replace -isysroot __BAZEL_XCODE_SDKROOT__ marker
128 |
129 | # Clean up backup file left behind by sed.
130 | rm "${COMPDB_FILE}.bak"
131 |
--------------------------------------------------------------------------------
/external/bazel-compilation-database/plugin/bazel-compilation-database.vim:
--------------------------------------------------------------------------------
1 | let g:ycm_global_ycm_extra_conf = expand(":p:h:h") . "/.ycm_extra_conf.py"
2 |
--------------------------------------------------------------------------------
/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "install": "messages/install.rst",
3 | "2.0.0": "messages/2.0.0.rst",
4 | "3.0.0": "messages/3.0.0.rst",
5 | "4.0.0": "messages/4.0.0.rst",
6 | "5.0.0": "messages/5.0.0.rst",
7 | "6.0.0": "messages/6.0.0.rst",
8 | "6.0.1": "messages/6.0.1.rst",
9 | "6.0.2": "messages/6.0.2.rst",
10 | "6.0.3": "messages/6.0.3.rst",
11 | "6.1.0": "messages/6.1.0.rst",
12 | "6.1.1": "messages/6.1.1.rst",
13 | "6.1.2": "messages/6.1.2.rst",
14 | "6.1.3": "messages/6.1.3.rst",
15 | "6.2.0": "messages/6.2.0.rst",
16 | "6.2.1": "messages/6.2.1.rst",
17 | "6.2.2": "messages/6.2.2.rst",
18 | "6.2.3": "messages/6.2.3.rst",
19 | "6.2.4": "messages/6.2.4.rst",
20 | "6.2.5": "messages/6.2.5.rst",
21 | "6.2.6": "messages/6.2.6.rst",
22 | "6.2.7": "messages/6.2.7.rst",
23 | "6.2.8": "messages/6.2.8.rst",
24 | "6.3.0": "messages/6.3.0.rst",
25 | "6.4.0": "messages/6.4.0.rst",
26 | "6.4.1": "messages/6.4.1.rst",
27 | "6.4.2": "messages/6.4.2.rst",
28 | "6.4.3": "messages/6.4.3.rst",
29 | "6.4.4": "messages/6.4.4.rst",
30 | "6.4.5": "messages/6.4.5.rst",
31 | "6.5.0": "messages/6.5.0.rst",
32 | "6.5.1": "messages/6.5.1.rst",
33 | "6.5.2": "messages/6.5.2.rst"
34 | }
35 |
--------------------------------------------------------------------------------
/messages/2.0.0.rst:
--------------------------------------------------------------------------------
1 | Version 2.0.0
2 | =============
3 |
4 | New features:
5 | -------------
6 |
7 | - **BIG CHANGE**: if your build system is `CMake` the plugin will generate a
8 | compilation database and then a file `.clang_complete` near an appropriate
9 | `CMakeLists.txt` with the flags needed for your project. It will regenerate
10 | this file if you change anything in `CMakeLists.txt`. The process should be
11 | completely automatic, but this behavior is still in beta. You can always
12 | disable it either from settings or when prompted via a dialog.
13 | - Lots of small improvements and bug fixes.
14 | - fix regression in loading relative paths from `.clang_complete` file.
15 | - support libclang with clang-3.8 on Ubuntu 16.04 with error linting and
16 | completions
17 | - initial support for libclang with clang-3.9
18 | - fix completions of arrays shown wrongly with binary comletion mode
19 | - thanks to @rchl:
20 | + fix hiding default completions when plugin completions were not generated
21 | + fix completions not working on active view after starting Sublime Text
22 | - fix for usage with OS X El Captain
23 | - since Sublime Text version 3123 libclang method should work on Windows with
24 | clang-3.9. Check it out!
25 | - when using libclang translation units are cleared based on timer to avoid
26 | taking all your memory in case you have many tabs open.
27 | - thanks to @rchl you don't need to restart Sublime Text in case you changed
28 | any settings.
29 | - thanks to @Mischa-Alff std flags are not separated anymore and the popup
30 | words don't break after every word on some systems
31 | - detection of cmake projects is now case insensitive as should be
32 | - NO MORE `include_dirs`, `std_flag_c`, `std_flag_cpp` SETTINGS!
33 | + use `common_flags`, `c_flags` and `cpp_flags` instead
34 | + to specify include paths, use `-I` in `common_flags`
35 | + specify `-std=*` flags in `c_flags` and/or `cpp_flags`
36 | + see updated default settings for an example
37 | - `libclang` way should be working on Windows with `clang` version >= 3.9
38 | - override any plugin setting from project-specific settings
39 | - completions can be triggered from any place (e.g. in the middle of words)
40 | with default sublime auto completion keyboard shortcut
41 | - completions will not be shown if you continue on typing for those rare slow
42 | completion requests.
43 | - new wildcard for `common_flags`: `$clang_version`. Allows for generic include
44 | folder for any version of clang
45 | - fixed a bunch of crashes and deadlocks, improved overall concurrency support
46 | - overall code base improvements and many-many bug fixes
47 |
--------------------------------------------------------------------------------
/messages/3.0.0.rst:
--------------------------------------------------------------------------------
1 | Version 3.0.0
2 | =============
3 |
4 | New features:
5 | -------------
6 |
7 | - add support for `-isysroot` flag for OSX, fix `-isystem` flag.
8 | - allow wider error popup windows
9 | - open plugin settings side-by-side just like sublime does with its settings
10 | - flags order is now preserved, so the flags are passed to clang in the same
11 | order as they appear in settings and/or .clang_complete file
12 | - fix the completions being shown in a wrong location after a long completion
13 | request has finished while the cursor was moved
14 | - Following settings not used anymore or updated:
15 | + `cmake_flags_priority`
16 | + `generate_flags_with_cmake`
17 | + `search_clang_complete_file`
18 | + `max_tu_age` changed to `max_cache_age`
19 | - `.clang_complete` file will not get generated by the plugin anymore. Instead,
20 | the flags are loaded directly from their source file, e.g. `CMakeLists.txt`,
21 | `compile_commands.json` or user-defined `.clang_complete`.
22 | - New setting introduced:
23 | + `flags_sources` to allow specifying where the plugin will try to get flags
24 | for compilation from.
25 | - When using `libclang` the plugin now filters private members, destructors,
26 | constructors and enums when needed. Thanks @simia for contribution.
27 |
--------------------------------------------------------------------------------
/messages/6.0.1.rst:
--------------------------------------------------------------------------------
1 | Version 6.0.1
2 | =============
3 |
4 | Bug fixes:
5 | -----------------------
6 | - Fix crash when trying to read "search_in" flag sources setting.
7 |
8 |
9 | Support the development!
10 | ------------------------
11 | 💜 this plugin? Please consider buying me a 🍵
12 | https://github.com/niosus/EasyClangComplete#support-it
13 |
14 | Thanks to all the awesome contributors!
15 | If you add bounties to Bountysource you can support them too!
16 | https://www.bountysource.com/teams/easyclangcomplete
17 |
18 | Become a backer on Open Collective!
19 | https://opencollective.com/EasyClangComplete#backers
20 |
21 | I you use this plugin in a company, push to become a sponsor!
22 | https://opencollective.com/EasyClangComplete#sponsor
23 |
24 | This plugin took a significant amount of effort. It is available and will always
25 | be available for free, both as freedom and as beer.
26 |
27 | If you appreciate it - support it. How much would you say it is worth to you?
28 |
--------------------------------------------------------------------------------
/messages/6.0.2.rst:
--------------------------------------------------------------------------------
1 | Version 6.0.2
2 | =============
3 |
4 | Bug fixes:
5 | ----------
6 | - Fix -cxx-isystem flag not parsed correctly.
7 | - Fix error with new list search scope.
8 | - Thanks to @mjendruk the wildcard "$project_base_path" will **not** be
9 | deprecated. Please ignore the message in version 6.0.0 release.
10 | "$project_base_path" has a different meaning than "$project_path". Both will
11 | be available for use.
12 |
13 |
14 | Support the development!
15 | ------------------------
16 | 💜 this plugin? Please consider buying me a 🍵
17 | https://github.com/niosus/EasyClangComplete#support-it
18 |
19 | Thanks to all the awesome contributors!
20 | If you add bounties to Bountysource you can support them too!
21 | https://www.bountysource.com/teams/easyclangcomplete
22 |
23 | Become a backer on Open Collective!
24 | https://opencollective.com/EasyClangComplete#backers
25 |
26 | I you use this plugin in a company, push to become a sponsor!
27 | https://opencollective.com/EasyClangComplete#sponsor
28 |
29 | This plugin took a significant amount of effort. It is available and will always
30 | be available for free, both as freedom and as beer.
31 |
32 | If you appreciate it - support it. How much would you say it is worth to you?
33 |
--------------------------------------------------------------------------------
/messages/6.0.3.rst:
--------------------------------------------------------------------------------
1 | Version 6.0.3
2 | =============
3 |
4 | Bug fixes and new features:
5 | ---------------------------
6 | - Fix cleaning cache when clearning CMake build.
7 | - Add support for different separators in flags. Fix parsing flags with spaces.
8 | - Travis ci config for Linux is updated to xenial. Build is green again.
9 |
10 | Support the development!
11 | ------------------------
12 | 💜 this plugin? Please consider buying me a 🍵
13 | https://github.com/niosus/EasyClangComplete#support-it
14 |
15 | Thanks to all the awesome contributors!
16 | If you add bounties to Bountysource you can support them too!
17 | https://www.bountysource.com/teams/easyclangcomplete
18 |
19 | Become a backer on Open Collective!
20 | https://opencollective.com/EasyClangComplete#backers
21 |
22 | I you use this plugin in a company, push to become a sponsor!
23 | https://opencollective.com/EasyClangComplete#sponsor
24 |
25 | This plugin took a significant amount of effort. It is available and will always
26 | be available for free, both as freedom and as beer.
27 |
28 | If you appreciate it - support it. How much would you say it is worth to you?
29 |
--------------------------------------------------------------------------------
/messages/6.1.0.rst:
--------------------------------------------------------------------------------
1 | Version 6.1.0
2 | =============
3 |
4 | Breaking changes:
5 | -----------------
6 | The compilation database is now parsed differently by default:
7 | + All entries are parsed in a lazy fashion by default.
8 | + This allows to load huge databases relatively quickly.
9 | + There is no more "all" entry added to the database.
10 | + If the file is not in the database and no mapping to an existing file found
11 | through "header_to_source_mapping" setting there will be no flags emmitted
12 | for this file.
13 | + To return old behavior, set "lazy_flag_parsing" setting to "false".
14 |
15 | Other changes:
16 | --------------
17 | - Resolve symlinks for file locations in info popup.
18 | - Resolve symlinks for files from compilation flags sources.
19 | - Show column and row when showing index.
20 |
21 | Support the development!
22 | ------------------------
23 | 💜 this plugin? Please consider buying me a 🍵
24 | https://github.com/niosus/EasyClangComplete#support-it
25 |
26 | Thanks to all the awesome contributors!
27 | If you add bounties to Bountysource you can support them too!
28 | https://www.bountysource.com/teams/easyclangcomplete
29 |
30 | Become a backer on Open Collective!
31 | https://opencollective.com/EasyClangComplete#backers
32 |
33 | I you use this plugin in a company, push to become a sponsor!
34 | https://opencollective.com/EasyClangComplete#sponsor
35 |
36 | This plugin took a significant amount of effort. It is available and will always
37 | be available for free, both as freedom and as beer.
38 |
39 | If you appreciate it - support it. How much would you say it is worth to you?
40 |
--------------------------------------------------------------------------------
/messages/6.1.1.rst:
--------------------------------------------------------------------------------
1 | Version 6.1.1
2 | =============
3 |
4 | Quick fix:
5 | ----------
6 | Add support for Apple Clang 11.0
7 |
8 | Support the development!
9 | ------------------------
10 | 💜 this plugin? Please consider buying me a 🍵
11 | https://github.com/niosus/EasyClangComplete#support-it
12 |
13 | Thanks to all the awesome contributors!
14 | If you add bounties to Bountysource you can support them too!
15 | https://www.bountysource.com/teams/easyclangcomplete
16 |
17 | Become a backer on Open Collective!
18 | https://opencollective.com/EasyClangComplete#backers
19 |
20 | I you use this plugin in a company, push to become a sponsor!
21 | https://opencollective.com/EasyClangComplete#sponsor
22 |
23 | This plugin took a significant amount of effort. It is available and will always
24 | be available for free, both as freedom and as beer.
25 |
26 | If you appreciate it - support it. How much would you say it is worth to you?
27 |
--------------------------------------------------------------------------------
/messages/6.1.2.rst:
--------------------------------------------------------------------------------
1 | Version 6.1.1
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Add .so.8 prefix, thanks @jeeb
7 | - Move user-defined flags to the end of all flags to allow overriding generated ones
8 | - When showing an error dialog, tell the user it comes from ECC
9 |
10 | Support the development!
11 | ------------------------
12 | 💜 this plugin? Please consider buying me a 🍵
13 | https://github.com/niosus/EasyClangComplete#support-it
14 |
15 | Thanks to all the awesome contributors!
16 | If you add bounties to Bountysource you can support them too!
17 | https://www.bountysource.com/teams/easyclangcomplete
18 |
19 | Become a backer on Open Collective!
20 | https://opencollective.com/EasyClangComplete#backers
21 |
22 | I you use this plugin in a company, push to become a sponsor!
23 | https://opencollective.com/EasyClangComplete#sponsor
24 |
25 | This plugin took a significant amount of effort. It is available and will always
26 | be available for free, both as freedom and as beer.
27 |
28 | If you appreciate it - support it. How much would you say it is worth to you?
29 |
--------------------------------------------------------------------------------
/messages/6.1.3.rst:
--------------------------------------------------------------------------------
1 | Version 6.1.3
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Support Clang 9
7 | - Avoid crashing when expanding an invalid path
8 | - Allow working with ccache, thanks @maximmenshikov
9 | - Grammar fixes in docs, thanks @ryanpcmcquen
10 |
11 | Support the development!
12 | ------------------------
13 | 💜 this plugin? Please consider buying me a 🍵
14 | https://github.com/niosus/EasyClangComplete#support-it
15 |
16 | Thanks to all the awesome contributors!
17 | If you add bounties to Bountysource you can support them too!
18 | https://www.bountysource.com/teams/easyclangcomplete
19 |
20 | Become a backer on Open Collective!
21 | https://opencollective.com/EasyClangComplete#backers
22 |
23 | I you use this plugin in a company, push to become a sponsor!
24 | https://opencollective.com/EasyClangComplete#sponsor
25 |
26 | This plugin took a significant amount of effort. It is available and will always
27 | be available for free, both as freedom and as beer.
28 |
29 | If you appreciate it - support it. How much would you say it is worth to you?
30 |
--------------------------------------------------------------------------------
/messages/6.2.0.rst:
--------------------------------------------------------------------------------
1 | Version 6.2.0
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Add linter visualization settings, thanks @oakmountainapps
7 | - New setting: "linter_mark_style": "outline", see docs
8 | - Refactor getting default flags from compilers
9 | - Refactor tools module to aid future extensibility and testability
10 |
11 | Support the development!
12 | ------------------------
13 | 💜 this plugin? Please consider buying me a 🍵
14 | https://github.com/niosus/EasyClangComplete#support-it
15 |
16 | Thanks to all the awesome contributors!
17 | If you add bounties to Bountysource you can support them too!
18 | https://www.bountysource.com/teams/easyclangcomplete
19 |
20 | Become a backer on Open Collective!
21 | https://opencollective.com/EasyClangComplete#backers
22 |
23 | I you use this plugin in a company, push to become a sponsor!
24 | https://opencollective.com/EasyClangComplete#sponsor
25 |
26 | This plugin took a significant amount of effort. It is available and will always
27 | be available for free, both as freedom and as beer.
28 |
29 | If you appreciate it - support it. How much would you say it is worth to you?
30 |
--------------------------------------------------------------------------------
/messages/6.2.1.rst:
--------------------------------------------------------------------------------
1 | Version 6.2.1
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Expand the entries in the header_to_source_mapping setting
7 | - Make ignore list more powerful by not filtering out stars in it
8 |
9 | Support the development!
10 | ------------------------
11 | 💜 this plugin? Please consider buying me a 🍵
12 | https://github.com/niosus/EasyClangComplete#support-it
13 |
14 | Thanks to all the awesome contributors!
15 | If you add bounties to Bountysource you can support them too!
16 | https://www.bountysource.com/teams/easyclangcomplete
17 |
18 | Become a backer on Open Collective!
19 | https://opencollective.com/EasyClangComplete#backers
20 |
21 | I you use this plugin in a company, push to become a sponsor!
22 | https://opencollective.com/EasyClangComplete#sponsor
23 |
24 | This plugin took a significant amount of effort. It is available and will always
25 | be available for free, both as freedom and as beer.
26 |
27 | If you appreciate it - support it. How much would you say it is worth to you?
28 |
--------------------------------------------------------------------------------
/messages/6.2.2.rst:
--------------------------------------------------------------------------------
1 | Version 6.2.2
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Strip "(framework directory)" for macOS builds, thanks @saagarjha
7 | - Disambiguate warnings from errors by the gutter icon
8 | - Disable loading default definitions from a compiler by default as it seems
9 | to cause quite a bit of problems. To restore the behavior just enable:
10 | "use_default_definitions": true
11 |
12 | 💜 this plugin? Consider supporting its development! 💰💸💶
13 | ------------------------------------------------------------
14 | ‼️NEW‼️ Head to GitHub Sponsors and support my work if you enjoy the plugin!
15 | https://github.com/sponsors/niosus
16 |
17 | Alternatively, become a backer on Open Collective!
18 | https://opencollective.com/EasyClangComplete#backers
19 |
20 | I you use this plugin in a company, push to become a sponsor!
21 | https://opencollective.com/EasyClangComplete#sponsor
22 |
23 | This plugin took a significant amount of effort. It is available and will always
24 | be available for free, both as freedom and as beer.
25 |
26 | If you appreciate it - support it. How much would you say it is worth to you?
27 |
28 | For more info head here:
29 | https://github.com/niosus/EasyClangComplete#support-it
30 |
--------------------------------------------------------------------------------
/messages/6.2.3.rst:
--------------------------------------------------------------------------------
1 | Version 6.2.3
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - New setting "ignore_flags":
7 | You can now set up a list of patterns to ignore flags you don't want to be
8 | passed to clang. This is useful, when there is, say, gcc-specific header in
9 | the include flags and you want to get rid of it as it causes compilation
10 | issues for clang.
11 |
12 | 💜 this plugin? Consider supporting its development! 💰💸💶
13 | ------------------------------------------------------------
14 | ‼️NEW‼️ Head to GitHub Sponsors and support my work if you enjoy the plugin!
15 | https://github.com/sponsors/niosus
16 |
17 | Alternatively, become a backer on Open Collective!
18 | https://opencollective.com/EasyClangComplete#backers
19 |
20 | I you use this plugin in a company, push to become a sponsor!
21 | https://opencollective.com/EasyClangComplete#sponsor
22 |
23 | This plugin took a significant amount of effort. It is available and will always
24 | be available for free, both as freedom and as beer.
25 |
26 | If you appreciate it - support it. How much would you say it is worth to you?
27 |
28 | For more info head here:
29 | https://github.com/niosus/EasyClangComplete#support-it
30 |
--------------------------------------------------------------------------------
/messages/6.2.4.rst:
--------------------------------------------------------------------------------
1 | Version 6.2.4
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Fix the issue of `clang_binary` not expanding wildcards and variables
7 |
8 | 💜 this plugin? Consider supporting its development! 💰💸💶
9 | ------------------------------------------------------------
10 | ‼️NEW‼️ Head to GitHub Sponsors and support my work if you enjoy the plugin!
11 | https://github.com/sponsors/niosus
12 |
13 | Alternatively, become a backer on Open Collective!
14 | https://opencollective.com/EasyClangComplete#backers
15 |
16 | I you use this plugin in a company, push to become a sponsor!
17 | https://opencollective.com/EasyClangComplete#sponsor
18 |
19 | This plugin took a significant amount of effort. It is available and will always
20 | be available for free, both as freedom and as beer.
21 |
22 | If you appreciate it - support it. How much would you say it is worth to you?
23 |
24 | For more info head here:
25 | https://github.com/niosus/EasyClangComplete#support-it
26 |
--------------------------------------------------------------------------------
/messages/6.2.5.rst:
--------------------------------------------------------------------------------
1 | Version 6.2.5
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | This is mostly a dev release that increases test coverage.
7 | No functionality should be changed on the user side.
8 |
9 | 💜 this plugin? Consider supporting its development! 💰💸💶
10 | ------------------------------------------------------------
11 | ‼️NEW‼️ Head to GitHub Sponsors and support my work if you enjoy the plugin!
12 | https://github.com/sponsors/niosus
13 |
14 | Alternatively, become a backer on Open Collective!
15 | https://opencollective.com/EasyClangComplete#backers
16 |
17 | I you use this plugin in a company, push to become a sponsor!
18 | https://opencollective.com/EasyClangComplete#sponsor
19 |
20 | This plugin took a significant amount of effort. It is available and will always
21 | be available for free, both as freedom and as beer.
22 |
23 | If you appreciate it - support it. How much would you say it is worth to you?
24 |
25 | For more info head here:
26 | https://github.com/niosus/EasyClangComplete#support-it
27 |
--------------------------------------------------------------------------------
/messages/6.2.6.rst:
--------------------------------------------------------------------------------
1 | Version 6.2.6
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Fix a bug using the wrong row for showing error popup
7 |
8 | 💜 this plugin? Consider supporting its development! 💰💸💶
9 | ------------------------------------------------------------
10 | ‼️NEW‼️ Head to GitHub Sponsors and support my work if you enjoy the plugin!
11 | https://github.com/sponsors/niosus
12 |
13 | Alternatively, become a backer on Open Collective!
14 | https://opencollective.com/EasyClangComplete#backers
15 |
16 | I you use this plugin in a company, push to become a sponsor!
17 | https://opencollective.com/EasyClangComplete#sponsor
18 |
19 | This plugin took a significant amount of effort. It is available and will always
20 | be available for free, both as freedom and as beer.
21 |
22 | If you appreciate it - support it. How much would you say it is worth to you?
23 |
24 | For more info head here:
25 | https://github.com/niosus/EasyClangComplete#support-it
26 |
--------------------------------------------------------------------------------
/messages/6.2.7.rst:
--------------------------------------------------------------------------------
1 | Version 6.2.7
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Fix the off-by-one error when showing compilation errors
7 | - Fix not being able to use ECC on multi-user system
8 | - Slight refactoring of the code
9 |
10 | Warning:
11 | --------
12 | You might need to restart Sublime Text after this update.
13 |
14 |
15 | 💜 this plugin? Consider supporting its development! 💰💸💶
16 | ------------------------------------------------------------
17 | ‼️NEW‼️ Head to GitHub Sponsors and support my work if you enjoy the plugin!
18 | https://github.com/sponsors/niosus
19 |
20 | Alternatively, become a backer on Open Collective!
21 | https://opencollective.com/EasyClangComplete#backers
22 |
23 | I you use this plugin in a company, push to become a sponsor!
24 | https://opencollective.com/EasyClangComplete#sponsor
25 |
26 | This plugin took a significant amount of effort. It is available and will always
27 | be available for free, both as freedom and as beer.
28 |
29 | If you appreciate it - support it. How much would you say it is worth to you?
30 |
31 | For more info head here:
32 | https://github.com/niosus/EasyClangComplete#support-it
33 |
--------------------------------------------------------------------------------
/messages/6.2.8.rst:
--------------------------------------------------------------------------------
1 | Version 6.2.8
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Fix flag parsing for paths starting with `/U`.
7 |
8 |
9 | 💜 this plugin? Consider supporting its development! 💰💸💶
10 | ------------------------------------------------------------
11 | ‼️NEW‼️ Head to GitHub Sponsors and support my work if you enjoy the plugin!
12 | https://github.com/sponsors/niosus
13 |
14 | Alternatively, become a backer on Open Collective!
15 | https://opencollective.com/EasyClangComplete#backers
16 |
17 | I you use this plugin in a company, push to become a sponsor!
18 | https://opencollective.com/EasyClangComplete#sponsor
19 |
20 | This plugin took a significant amount of effort. It is available and will always
21 | be available for free, both as freedom and as beer.
22 |
23 | If you appreciate it - support it. How much would you say it is worth to you?
24 |
25 | For more info head here:
26 | https://github.com/niosus/EasyClangComplete#support-it
27 |
--------------------------------------------------------------------------------
/messages/6.3.0.rst:
--------------------------------------------------------------------------------
1 | Version 6.3.0
2 | =============
3 |
4 | Generate compilation database with Bazel!
5 | -----------------------------------------
6 | There is a new option available for everyone using Bazel on Linux and OSX.
7 | It is still experimental, but seems to be working.
8 |
9 | If you have a Bazel project, open any file in it and call the command:
10 | "ECC: (Bazel) Generate compile_commands.json"
11 |
12 | This will use https://github.com/grailbio/bazel-compilation-database
13 | It generates a compilation database and if it fails it shows the error
14 | in an output panel. The approximate sequence of actions is as follows:
15 |
16 | - Search for a folder with a WORKSPACE file up the tree.
17 | - Run a script "generate.sh" from the repo in that folder.
18 | - If the command fails, show the output.
19 |
20 | 👏🧼 Stay safe!
21 | ---------------
22 | Hope everyone is staying safe in these weird times! This is a good time to
23 | stay at home and delve into that side-project you've been postponing for ages!
24 |
--------------------------------------------------------------------------------
/messages/6.4.0.rst:
--------------------------------------------------------------------------------
1 | Version 6.4.0
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Show which command is running along with the progress status.
7 |
8 | 👏🧼 Stay safe!
9 | ---------------
10 | Hope everyone is staying safe in these weird times! This is a good time to
11 | stay at home and delve into that side-project you've been postponing for ages!
12 |
13 |
14 | 💜 this plugin? Consider supporting its development! 💰💸💶
15 | ------------------------------------------------------------
16 | ‼️NEW‼️ Head to GitHub Sponsors and support my work if you enjoy the plugin!
17 | https://github.com/sponsors/niosus
18 |
19 | Alternatively, become a backer on Open Collective!
20 | https://opencollective.com/EasyClangComplete#backers
21 |
22 | I you use this plugin in a company, push to become a sponsor!
23 | https://opencollective.com/EasyClangComplete#sponsor
24 |
25 | This plugin took a significant amount of effort. It is available and will always
26 | be available for free, both as freedom and as beer.
27 |
28 | If you appreciate it - support it. How much would you say it is worth to you?
29 |
30 | For more info head here:
31 | https://github.com/niosus/EasyClangComplete#support-it
32 |
--------------------------------------------------------------------------------
/messages/6.4.1.rst:
--------------------------------------------------------------------------------
1 | Version 6.4.1
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Fix progress showing a wrong job name.
7 | - Show console output if CMake generation fails.
8 | - Fix cmake flags source overwriting CMAKE_PREFIX_PATHS environment variable.
9 | - Add more suffixes to find libclang, thanks @jeeb.
10 | - Fix docs generation after updating the theme.
11 |
12 | Development announcement:
13 | -------------------------
14 | I decided to move away from using the "dev" branch. Now all the development
15 | will be happening in the "master" branch. The releases will be sourced from
16 | the "release" branch. See contribution guidelines for details.
17 |
18 |
19 | 💜 this plugin? Consider supporting its development! 💰💸💶
20 | ------------------------------------------------------------
21 | ‼️NEW‼️ Head to GitHub Sponsors and support my work if you enjoy the plugin!
22 | https://github.com/sponsors/niosus
23 |
24 | Alternatively, become a backer on Open Collective!
25 | https://opencollective.com/EasyClangComplete#backers
26 |
27 | I you use this plugin in a company, push to become a sponsor!
28 | https://opencollective.com/EasyClangComplete#sponsor
29 |
30 | This plugin took a significant amount of effort. It is available and will always
31 | be available for free, both as freedom and as beer.
32 |
33 | If you appreciate it - support it. How much would you say it is worth to you?
34 |
35 | For more info head here:
36 | https://github.com/niosus/EasyClangComplete#support-it
37 |
--------------------------------------------------------------------------------
/messages/6.4.2.rst:
--------------------------------------------------------------------------------
1 | Version 6.4.2
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Add proper failure detection of CMake run.
7 |
8 |
9 | 💜 this plugin? Consider supporting its development! 💰💸💶
10 | ------------------------------------------------------------
11 | ‼️NEW‼️ Head to GitHub Sponsors and support my work if you enjoy the plugin!
12 | https://github.com/sponsors/niosus
13 |
14 | Alternatively, become a backer on Open Collective!
15 | https://opencollective.com/EasyClangComplete#backers
16 |
17 | If you use this plugin in a company, push to become a sponsor!
18 | https://opencollective.com/EasyClangComplete#sponsor
19 |
20 | This plugin took a significant amount of effort. It is available and will always
21 | be available for free, both as freedom and as beer.
22 |
23 | If you appreciate it - support it. How much would you say it is worth to you?
24 |
25 | For more info head here:
26 | https://github.com/niosus/EasyClangComplete#support-it
27 |
--------------------------------------------------------------------------------
/messages/6.4.3.rst:
--------------------------------------------------------------------------------
1 | Version 6.4.3
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - More powerful cmake-related flags parsing. If you ever wanted to use flags
7 | like `-DCMAKE_PREFIX_PATH=~/some_path/*`, now you can!
8 | See [1] for details.
9 | - **WARNING**: the sub-setting of the `CMakeLists.txt` entry `prefix_paths`
10 | is now deprecated as all the functionality is covered by the more useful
11 | `flags` sub-setting. You can still use it for now, but I will remove it
12 | in the future.
13 | - Fixed a jump to a wrong location when going to declaration, thanks @berteauxjb
14 | - Fixed typo in the message below, thanks @berkus
15 |
16 | [1]: https://niosus.github.io/EasyClangComplete/settings/#cmake-specific-options
17 |
18 | Love this plugin? Support its development! 💰💸💶
19 | -------------------------------------------------
20 | ‼️NEW‼️ Head to GitHub Sponsors and support my work if you enjoy the plugin!
21 | https://github.com/sponsors/niosus
22 |
23 | Alternatively, become a backer on Open Collective!
24 | https://opencollective.com/EasyClangComplete#backers
25 |
26 | If you use this plugin in a company, push to become a sponsor!
27 | https://opencollective.com/EasyClangComplete#sponsor
28 |
29 | This plugin took a significant amount of effort. It is available and will always
30 | be available for free, both as freedom and as beer.
31 |
32 | If you appreciate it - support it. How much would you say it is worth to you?
33 |
34 | For more info head here:
35 | https://github.com/niosus/EasyClangComplete#support-it
36 |
--------------------------------------------------------------------------------
/messages/6.4.4.rst:
--------------------------------------------------------------------------------
1 | Version 6.4.4
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Fixed a bug when calling "ECC: clean current cmake cache".
7 | It now works as expected.
8 |
9 | Love this plugin? Support its development! 💰💸💶
10 | -------------------------------------------------
11 | If you appreciate it - support it. How much would you say it is worth to you?
12 | This plugin took a significant amount of effort. It is available and will always
13 | be available for free, both as freedom and as beer.
14 |
15 | GitHub Sponsors is the preferred way to support the development
16 | https://github.com/sponsors/niosus
17 |
18 | Alternatively, become a backer on Open Collective!
19 | https://opencollective.com/EasyClangComplete#backers
20 |
21 | If you use this plugin in a company, push to become a sponsor!
22 | https://opencollective.com/EasyClangComplete#sponsor
23 |
24 | For more info head here:
25 | https://github.com/niosus/EasyClangComplete#support-it
26 |
--------------------------------------------------------------------------------
/messages/6.4.5.rst:
--------------------------------------------------------------------------------
1 | Version 6.4.5
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - Add `-target` as a separable flag, thanks @papadokolos
7 | - Fix a bug in parsing flags with =, thanks @papadokolos
8 | - Parse non-posix compilation dbs on non-posix systems, thanks @papadokolos
9 | - Update docs about `$project_base_path`, thanks @dot4qu
10 | - Fix missing enum completions
11 |
12 | Hey! It's been a while!
13 | -----------------------
14 | There has not been updates for a while and I think it is good. The plugin still
15 | gets installed often but there is really not that many issues being opened. I
16 | understand, however, that not everyone will open an issue if something does not
17 | work.
18 |
19 | At this point, I would like to ask you to take action:
20 | - If something does not work - please open an issue! It will force me to go
21 | back to work on this.
22 | - If everything has been working without much updates: consider supporting this
23 | development. Sending some money my way is always welcome, but if you don't have
24 | any to spare - shoot me an email (or open an issue) and tell about how you use
25 | the plugin.
26 |
27 | At this point, with >35K downloads I feel a bit discouraged by the lack of
28 | feedback and it is hard to put in work on issues that I don't personally
29 | experience after a full day of work. If you appreciate this effort, do show
30 | your support.
31 |
32 | GitHub Sponsors is the preferred way to support the development
33 | https://github.com/sponsors/niosus
34 |
35 | Alternatively, become a backer on Open Collective!
36 | https://opencollective.com/EasyClangComplete#backers
37 |
38 | If you use this plugin in a company, push to become a sponsor!
39 | https://opencollective.com/EasyClangComplete#sponsor
40 |
41 | For more info head here:
42 | https://github.com/niosus/EasyClangComplete#support-it
43 |
--------------------------------------------------------------------------------
/messages/6.5.0.rst:
--------------------------------------------------------------------------------
1 | Version 6.5.0
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - New include autocompletion!
7 | - New setting "autocomplete_includes" defaulted to true, so make
8 | sure to reload sublime text!
9 | - Press `<` or `"` after `#include` to open quick panel with guided
10 | completion for your includes. The initial list is populated from
11 | the current translation unit (make sure the initial parsing is
12 | complete!) while the next layers stem from chosen folders. In the
13 | end, the picked file is committed to file.
14 | - Details here:
15 | https://niosus.github.io/EasyClangComplete/settings/#autocomplete_includes
16 | - Info popup now also shows references from open files.
17 | - Get rid of a singleton in the thread pool. Use a single instance per
18 | plugin.
19 |
20 | Huuuge thanks to my GitHub Sponsors! You're amazing! 🙏
21 | -------------------------------------------------------
22 | - @vaporstack
23 | - @Andreasdahlberg
24 |
25 | Join them on GitHub Sponsors and support the development!
26 | https://github.com/sponsors/niosus
27 |
28 | Reach out! 😉
29 | -------------
30 |
31 | Tell me how YOU use the plugin! Tweet at me at @igor_niosus 🐦
32 |
33 | Other means of support here:
34 | https://github.com/niosus/EasyClangComplete#support-it
35 |
--------------------------------------------------------------------------------
/messages/6.5.1.rst:
--------------------------------------------------------------------------------
1 | Version 6.5.1
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - ECC now plays well with other panels being open and won't force
7 | close them in case CMake has failed.
8 |
9 | Huuuge thanks to my GitHub Sponsors! You're amazing! 🙏
10 | -------------------------------------------------------
11 | - @vaporstack
12 | - @Andreasdahlberg
13 |
14 | Join them on GitHub Sponsors and support the development!
15 | https://github.com/sponsors/niosus
16 |
17 | Reach out! 😉
18 | -------------
19 |
20 | Tell me how YOU use the plugin!
21 | - PM me on reddit: @soinus
22 | - Tweet at me on twitter: @igor_niosus 🐦
23 |
24 | Other means of support here:
25 | https://github.com/niosus/EasyClangComplete#support-it
26 |
--------------------------------------------------------------------------------
/messages/6.5.2.rst:
--------------------------------------------------------------------------------
1 | Version 6.5.2
2 | =============
3 |
4 | Improvements and bug fixes:
5 | ---------------------------
6 | - A fix for a missing flag for M1 Apple arm architecture
7 | - [dev] Rewrite the CI setup to ease further development
8 |
9 | Huuuge thanks to my GitHub Sponsors! You're amazing! 🙏
10 | -------------------------------------------------------
11 | - @vaporstack
12 | - @Andreasdahlberg
13 |
14 | Join them on GitHub Sponsors and support the development!
15 | https://github.com/sponsors/niosus
16 |
17 | Reach out! 😉
18 | -------------
19 |
20 | Tell me how YOU are using the plugin!
21 | - PM me on reddit: @soinus
22 | - Tweet at me on twitter: @igor_niosus 🐦
23 |
24 | Other means of support here:
25 | ----------------------------
26 | https://github.com/niosus/EasyClangComplete#support-it
27 |
--------------------------------------------------------------------------------
/messages/install.rst:
--------------------------------------------------------------------------------
1 | A plugin for easy to use clang-based completions::
2 |
3 | ╔═╗┌─┐┌─┐┬ ┬ ╔═╗┬ ┌─┐┌┐┌┌─┐ ╔═╗┌─┐┌┬┐┌─┐┬ ┌─┐┌┬┐┌─┐
4 | ║╣ ├─┤└─┐└┬┘ ║ │ ├─┤││││ ┬ ║ │ ││││├─┘│ ├┤ │ ├┤
5 | ╚═╝┴ ┴└─┘ ┴ ╚═╝┴─┘┴ ┴┘└┘└─┘ ╚═╝└─┘┴ ┴┴ ┴─┘└─┘ ┴ └─┘
6 |
7 | Let't get started!
8 | ==================
9 |
10 | You're just two steps away!
11 |
12 | 1. Install clang
13 | ----------------
14 |
15 | - **Ubuntu** : ``sudo apt-get install clang``
16 | - **OSX** : ships `clang` by default. You are all set!
17 | - **Windows** : install the latest release from clang website.
18 | - **Other Systems** : use your package manager or install from clang website.
19 | - clang website: http://llvm.org/releases/download.html
20 |
21 | 2. Configure your includes
22 | --------------------------
23 |
24 | Using CMake?
25 | ~~~~~~~~~~~~
26 |
27 | Plugin will run cmake on a proper ``CMakeLists.txt`` in your project folder and
28 | will use information from it to complete your code out of the box.
29 |
30 | Don't like CMake?
31 | ~~~~~~~~~~~~~~~~~~
32 |
33 | There are many ways of configuring the plugin!
34 | Read the docs here: https://niosus.github.io/EasyClangComplete/configs/
35 |
36 | That's it! You're ready to use the plugin!
37 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38 |
39 | Intro and Documentation
40 | ~~~~~~~~~~~~~~~~~~~~~~~
41 |
42 | https://niosus.github.io/EasyClangComplete/
43 |
44 | Thanks!
45 | =======
46 |
47 | 💜 this plugin? Consider buying me a 🍵
48 | https://niosus.github.io/EasyClangComplete/support/
49 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: EasyClangComplete
2 | nav:
3 | - Getting started: index.md
4 | - Configure compiler flags: configs.md
5 | - Complete includes: includes_completion.md
6 | - Full settings guide: settings.md
7 | - Available commands: commands.md
8 | - About me: about.md
9 | - Credits: credits.md
10 | - Support this project: support.md
11 | theme:
12 | name: 'material'
13 | palette:
14 | primary: 'teal'
15 | accent: 'cyan'
16 | logo: 'img/ecc.png'
17 | favicon: 'img/favicon.ico'
18 | extra:
19 | social:
20 | - icon: fontawesome/brands/github
21 | link: https://github.com/niosus
22 | - icon: fontawesome/brands/linkedin
23 | link: https://www.linkedin.com/in/igor-bogoslavskyi-72650b43/
24 |
25 | copyright: 'Copyright © 2015 - 2020 Igor Bogoslavskyi'
26 |
27 | markdown_extensions:
28 | - admonition
29 | - codehilite
30 | - pymdownx.arithmatex
31 | - pymdownx.betterem:
32 | smart_enable: all
33 | - pymdownx.caret
34 | - pymdownx.critic
35 | - pymdownx.details
36 | - pymdownx.emoji:
37 | emoji_generator: !!python/name:pymdownx.emoji.to_svg
38 | - pymdownx.inlinehilite
39 | - pymdownx.magiclink
40 | - pymdownx.mark
41 | - pymdownx.smartsymbols
42 | - pymdownx.superfences
43 | - pymdownx.tasklist:
44 | custom_checkbox: true
45 | - pymdownx.tilde
46 | - toc:
47 | permalink: true
48 |
--------------------------------------------------------------------------------
/pics/ecc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/pics/ecc.png
--------------------------------------------------------------------------------
/pics/icons/dot.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
69 |
--------------------------------------------------------------------------------
/pics/icons/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/pics/icons/error.png
--------------------------------------------------------------------------------
/pics/icons/error.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
79 |
--------------------------------------------------------------------------------
/pics/icons/error_dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/pics/icons/error_dot.png
--------------------------------------------------------------------------------
/pics/icons/error_mono.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/pics/icons/error_mono.png
--------------------------------------------------------------------------------
/pics/icons/warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/pics/icons/warning.png
--------------------------------------------------------------------------------
/pics/icons/warning.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
92 |
--------------------------------------------------------------------------------
/pics/icons/warning_dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/pics/icons/warning_dot.png
--------------------------------------------------------------------------------
/pics/icons/warning_mono.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/pics/icons/warning_mono.png
--------------------------------------------------------------------------------
/plugin/__init__.py:
--------------------------------------------------------------------------------
1 | """Module that holds all the functionality of ECC."""
2 |
--------------------------------------------------------------------------------
/plugin/clang/__init__.py:
--------------------------------------------------------------------------------
1 | """Module that handles libclang python bindings."""
2 |
--------------------------------------------------------------------------------
/plugin/clang/enumerations.py:
--------------------------------------------------------------------------------
1 | #===- enumerations.py - Python Enumerations ------------------*- python -*--===#
2 | #
3 | # The LLVM Compiler Infrastructure
4 | #
5 | # This file is distributed under the University of Illinois Open Source
6 | # License. See LICENSE.TXT for details.
7 | #
8 | #===------------------------------------------------------------------------===#
9 |
10 | """
11 | Clang Enumerations
12 | ==================
13 | This module provides static definitions of enumerations that exist in libclang.
14 | Enumerations are typically defined as a list of tuples. The exported values are
15 | typically munged into other types or classes at module load time.
16 | All enumerations are centrally defined in this file so they are all grouped
17 | together and easier to audit. And, maybe even one day this file will be
18 | automatically generated by scanning the libclang headers!
19 | """
20 |
21 | # Maps to CXTokenKind. Note that libclang maintains a separate set of token
22 | # enumerations from the C++ API.
23 | TokenKinds = [
24 | ('PUNCTUATION', 0),
25 | ('KEYWORD', 1),
26 | ('IDENTIFIER', 2),
27 | ('LITERAL', 3),
28 | ('COMMENT', 4),
29 | ]
30 |
31 | __all__ = ['TokenKinds']
32 |
--------------------------------------------------------------------------------
/plugin/completion/__init__.py:
--------------------------------------------------------------------------------
1 | """Module that handles completion."""
2 |
--------------------------------------------------------------------------------
/plugin/completion/base_complete.py:
--------------------------------------------------------------------------------
1 | """Contains base class for completers.
2 |
3 | Attributes:
4 | log (logging.Logger): logger for this module
5 |
6 | """
7 | import logging
8 |
9 | from ..utils.subl.subl_bridge import SublBridge
10 |
11 | log = logging.getLogger("ECC")
12 |
13 |
14 | class BaseCompleter:
15 | """A base class for clang based completions.
16 |
17 | Attributes:
18 | compiler_variant (CompilerVariant): compiler specific options
19 | valid (bool): is completer valid
20 | version_str (str): version string of format "3.4.0"
21 | error_vis (obj): an object of error visualizer
22 | """
23 | name = "base"
24 |
25 | valid = False
26 |
27 | def __init__(self, settings, error_vis):
28 | """Initialize the BaseCompleter.
29 |
30 | Args:
31 | settings (SettingsStorage): an object that stores current settings
32 | error_vis (ErrorVis): an object of error visualizer
33 |
34 | Raises:
35 | RuntimeError: if clang not defined we throw an error
36 |
37 | """
38 | # check if clang binary is defined
39 | if not settings.clang_binary:
40 | raise RuntimeError("clang binary not defined")
41 |
42 | self.compiler_variant = None
43 | self.version_str = settings.clang_version
44 | self.clang_binary = settings.clang_binary
45 | # initialize error visualization
46 | self.error_vis = error_vis
47 | # Store the latest errors here
48 | self.latest_errors = None
49 |
50 | def complete(self, completion_request):
51 | """Generate completions. See children for implementation.
52 |
53 | Args:
54 | completion_request (ActionRequest): request object
55 |
56 | Raises:
57 | NotImplementedError: Guarantees we do not call this abstract method
58 | """
59 | raise NotImplementedError("calling abstract method")
60 |
61 | def info(self, tooltip_request, settings):
62 | """Provide information about object in given location.
63 |
64 | Using the current translation unit it queries libclang for available
65 | information about cursor.
66 |
67 | Args:
68 | tooltip_request (tools.ActionRequest): A request for action
69 | from the plugin.
70 | settings: All plugin settings.
71 |
72 | Raises:
73 | NotImplementedError: Guarantees we do not call this abstract method
74 | """
75 | raise NotImplementedError("calling abstract method")
76 |
77 | def update(self, view, settings):
78 | """Update the completer for this view.
79 |
80 | This can increase consequent completion speeds or is needed to just
81 | show errors.
82 |
83 | Args:
84 | view (sublime.View): this view
85 | settings: all plugin settings
86 |
87 | Raises:
88 | NotImplementedError: Guarantees we do not call this abstract method
89 | """
90 | raise NotImplementedError("calling abstract method")
91 |
92 | def get_declaration_location(self, view, row_col):
93 | """Get location of declaration from given location in file.
94 |
95 | Args:
96 | view (sublime.View): current view.
97 | row_col (ZeroBasedRowCol): location of the cursor.
98 |
99 | Returns:
100 | Location: location of declaration
101 | """
102 | raise NotImplementedError("calling abstract method")
103 |
104 | def save_errors(self, output):
105 | """Generate and store the errors.
106 |
107 | Args:
108 | output (object): opaque output to be parsed by compiler variant
109 | """
110 | self.latest_errors = self.compiler_variant.errors_from_output(output)
111 |
112 | def show_errors(self, view):
113 | """Show current complie errors.
114 |
115 | Args:
116 | view (sublime.View): Current view
117 | """
118 | if not SublBridge.is_valid_view(view):
119 | log.error("cannot show errors. View became invalid!")
120 | return
121 | self.error_vis.generate(view, self.latest_errors)
122 | self.error_vis.show_errors(view)
123 |
--------------------------------------------------------------------------------
/plugin/error_vis/__init__.py:
--------------------------------------------------------------------------------
1 | """Module that handles error visualization."""
2 |
--------------------------------------------------------------------------------
/plugin/error_vis/popup.css:
--------------------------------------------------------------------------------
1 | .ECC .admonition
2 | {
3 | border-radius: 0rem;
4 | top: -3rem;
5 | margin-bottom: 0;
6 | }
7 | .ECC .admonition-title
8 | {
9 | border-radius: 0rem;
10 | }
11 |
--------------------------------------------------------------------------------
/plugin/flags_sources/__init__.py:
--------------------------------------------------------------------------------
1 | """Handle different flags sources."""
2 |
--------------------------------------------------------------------------------
/plugin/flags_sources/bazel.py:
--------------------------------------------------------------------------------
1 | """Stores a class that manages genberation of compilation db with Bazel."""
2 | from ..utils.output_panel_handler import OutputPanelHandler
3 | from ..utils.search_scope import TreeSearchScope
4 | from ..utils.tools import PKG_FOLDER
5 | from ..utils.tools import Tools
6 | from ..utils.file import File
7 |
8 | from os import path
9 |
10 | import logging
11 | log = logging.getLogger("ECC")
12 |
13 |
14 | class Bazel():
15 | """Collection of methods to generate a compilation database."""
16 |
17 | @staticmethod
18 | def generate_compdb(view):
19 | """Generate the compilation database."""
20 | OutputPanelHandler.hide_panel()
21 | output = ''
22 | workspace_file = File.search(
23 | 'WORKSPACE', TreeSearchScope(path.dirname(view.file_name())))
24 | if not workspace_file:
25 | return None
26 | cmd = [path.join(PKG_FOLDER, 'external',
27 | 'bazel-compilation-database', 'generate.sh')]
28 | output = Tools.run_command(cmd, cwd=workspace_file.folder)
29 | return output
30 |
31 | @staticmethod
32 | def compdb_generated(future):
33 | """Generate a compilation database."""
34 | if future.done() and not future.cancelled():
35 | output_text = future.result()
36 | log.debug("Database generated. Output: \n%s", output_text)
37 | if "ERROR: " in output_text:
38 | log.error("Could not generate compilation database. Output: %s",
39 | output_text)
40 | OutputPanelHandler.show(
41 | "Could not generate compilation database.\n" + output_text)
42 | else:
43 | OutputPanelHandler.show("Could not generate compilation database.")
44 |
--------------------------------------------------------------------------------
/plugin/flags_sources/flags_file.py:
--------------------------------------------------------------------------------
1 | """Stores a class that manages flags loading from .clang_complete files.
2 |
3 | Attributes:
4 | log (logging.Logger): current logger.
5 | """
6 | from .flags_source import FlagsSource
7 | from ..utils.file import File
8 | from ..utils.singleton import FlagsFileCache
9 | from ..utils.flag import Flag
10 |
11 | from os import path
12 |
13 | import logging
14 |
15 | log = logging.getLogger("ECC")
16 |
17 |
18 | class FlagsFile(FlagsSource):
19 | """Manages flags parsing from .clang_complete file.
20 |
21 | Attributes:
22 | cache (dict): Cache of all parsed files to date. Stored by full file
23 | path. Needed to avoid reparsing the file multiple times.
24 | path_for_file (dict): A path to a database for every source file path.
25 | """
26 | _FILE_NAME = ".clang_complete"
27 |
28 | def __init__(self, include_prefixes):
29 | """Initialize a flag file storage.
30 |
31 | Args:
32 | include_prefixes (str[]): A List of valid include prefixes.
33 | """
34 | super().__init__(include_prefixes)
35 | self._cache = FlagsFileCache()
36 |
37 | def get_flags(self, file_path=None, search_scope=None):
38 | """Get flags for file.
39 |
40 | Args:
41 | file_path (None, optional): A path to the query file.
42 | search_scope (SearchScope, optional): Where to search for a
43 | .clang_complete file.
44 |
45 | Returns:
46 | str[]: Return a list of flags in this .clang_complete file
47 | """
48 | # prepare search scope
49 | search_scope = self._update_search_scope_if_needed(
50 | search_scope, file_path)
51 | # check if we have a hashed version
52 | log.debug("[clang_complete_file]:[get]: for file %s", file_path)
53 | cached_flags_path = self._get_cached_from(file_path)
54 | log.debug("[clang_complete_file]:[cached]: '%s'", cached_flags_path)
55 | flags_file = File.search(self._FILE_NAME, search_scope)
56 | if not flags_file:
57 | return None
58 | flags_file_path = flags_file.full_path
59 | log.debug("[clang_complete_file]:[current]: '%s'", flags_file_path)
60 | if not flags_file_path:
61 | return None
62 |
63 | flags = None
64 | parsed_before = flags_file_path in self._cache
65 | if parsed_before:
66 | log.debug("[clang_complete_file]: found cached .clang_complete")
67 | cached_flags_path = flags_file_path
68 | flags_file_path_same = (flags_file_path == cached_flags_path)
69 | flags_file_same = File.is_unchanged(cached_flags_path)
70 | if flags_file_path_same and flags_file_same:
71 | log.debug("[clang_complete_file]:[unchanged]: load cached")
72 | return self._cache[cached_flags_path]
73 | log.debug("[clang_complete_file]:[changed]: load new")
74 | if cached_flags_path and cached_flags_path in self._cache:
75 | del self._cache[cached_flags_path]
76 | flags = self.__flags_from_clang_file(File(flags_file_path))
77 | if flags:
78 | self._cache[cached_flags_path] = flags
79 | if file_path:
80 | self._cache[file_path] = flags_file_path
81 | # now we return whatever we have
82 | return flags
83 |
84 | def __flags_from_clang_file(self, file):
85 | """Get flags from .clang_complete file.
86 |
87 | Args:
88 | file (File): A file objects that represents the file to parse.
89 |
90 | Returns:
91 | str[]: List of flags from file.
92 | """
93 | if not path.exists(file.full_path):
94 | log.debug(".clang_complete does not exist yet. No flags present.")
95 | return []
96 | if not file.loaded():
97 | log.error("cannot get flags from clang_complete_file. No file.")
98 | return []
99 |
100 | return Flag.tokenize_list(file.lines, file.folder)
101 |
--------------------------------------------------------------------------------
/plugin/flags_sources/flags_source.py:
--------------------------------------------------------------------------------
1 | """Holds an abstract class defining a flags source."""
2 | from os import path
3 |
4 | from ..utils.search_scope import TreeSearchScope
5 |
6 |
7 | class FlagsSource(object):
8 | """An abstract class defining a Flags Source."""
9 |
10 | def __init__(self, include_prefixes):
11 | """Initialize default flags storage."""
12 | self._include_prefixes = include_prefixes
13 |
14 | def get_flags(self, file_path=None, search_scope=None):
15 | """Get flags for a view path [ABSTRACT].
16 |
17 | Raises:
18 | NotImplementedError: Should not be called directly.
19 | """
20 | raise NotImplementedError("calling abstract method")
21 |
22 | @staticmethod
23 | def _update_search_scope_if_needed(search_scope, file_path):
24 | if not search_scope:
25 | # Search from current file up the tree.
26 | return TreeSearchScope(from_folder=path.dirname(file_path))
27 | # We already know what we are doing. Leave search scope unchanged.
28 | return search_scope
29 |
30 | def _get_cached_from(self, file_path):
31 | """Get cached path for file path.
32 |
33 | Args:
34 | file_path (str): Input file path.
35 |
36 | Returns:
37 | str: Path to the cached flag source path.
38 | """
39 | if file_path and file_path in self._cache:
40 | return self._cache[file_path]
41 | return None
42 |
--------------------------------------------------------------------------------
/plugin/flags_sources/makefile.py:
--------------------------------------------------------------------------------
1 | """Stores a class that manages flags loading from Makefiles.
2 |
3 | Attributes:
4 | log (logging.Logger): current logger.
5 | """
6 | from os import path
7 | import subprocess
8 | import shlex
9 | import logging
10 |
11 | from .flags_source import FlagsSource
12 | from ..utils.file import File
13 | from ..utils.singleton import MakefileCache
14 | from ..utils.flag import Flag
15 |
16 | log = logging.getLogger("ECC")
17 |
18 |
19 | class Makefile(FlagsSource):
20 | """Manages flags parsing from Makefiles.
21 |
22 | Attributes:
23 | cache (dict): Cache of all parsed files to date. Stored by full file
24 | path. Needed to avoid reparsing the file multiple times.
25 | """
26 | _FILE_NAME = "Makefile"
27 |
28 | def __init__(self, include_prefixes):
29 | """Initialize a flag file storage.
30 |
31 | Args:
32 | include_prefixes (str[]): A List of valid include prefixes.
33 | """
34 | super().__init__(include_prefixes)
35 | self._cache = MakefileCache()
36 |
37 | def get_flags(self, file_path=None, search_scope=None):
38 | """Get flags for file.
39 |
40 | Args:
41 | file_path (None, optional): A path to the query file.
42 | search_scope (SearchScope, optional): Where to search for a
43 | Makefile
44 |
45 | Returns:
46 | str[]: Return a list of flags in this Makefile
47 | """
48 | search_scope = self._update_search_scope_if_needed(
49 | search_scope, file_path)
50 | log.debug("[Makefile]:[get]: for file %s", file_path)
51 | makefile = File.search(self._FILE_NAME, search_scope)
52 | if not makefile:
53 | return None
54 | makefile_path = makefile.full_path
55 | log.debug("[Makefile]:[current]: '%s'", makefile_path)
56 | if not makefile_path:
57 | return None
58 | cached_makefile_path = self._get_cached_from(file_path)
59 | log.debug("[Makefile]:[cached]: '%s'", cached_makefile_path)
60 |
61 | if makefile_path in self._cache:
62 | log.debug("[Makefile]: found cached Makefile")
63 | cached_makefile_path = makefile_path
64 | if makefile_path == cached_makefile_path:
65 | if File.is_unchanged(cached_makefile_path):
66 | log.debug("[Makefile]:[unchanged]: load cached")
67 | return self._cache[cached_makefile_path]
68 | log.debug("[Makefile]:[changed]: load new")
69 | if cached_makefile_path and cached_makefile_path in self._cache:
70 | del self._cache[cached_makefile_path]
71 | flags = self.__flags_from_makefile(File(makefile_path))
72 | if flags:
73 | self._cache[makefile_path] = flags
74 | if file_path:
75 | self._cache[file_path] = makefile_path
76 | return flags
77 |
78 | def __flags_from_makefile(self, file):
79 | """Get flags from Makefile.
80 |
81 | Args:
82 | file (File): A file objects that represents the file to parse.
83 |
84 | Returns:
85 | str[]: List of flags from Makefile.
86 | """
87 | if not path.exists(file.full_path) or not file.loaded():
88 | log.error("cannot get flags from Makefile. No file.")
89 | return []
90 |
91 | cmd = [
92 | "make", "-s", "-C", file.folder,
93 | "-f", self._FILE_NAME, "-f", "-",
94 | ]
95 | makevars = [
96 | "DEFAULT_INCLUDES",
97 | "INCLUDES",
98 | "AM_CPPFLAGS",
99 | "CPPFLAGS",
100 | "AM_CFLAGS",
101 | "CFLAGS",
102 | ]
103 | for makevar in makevars:
104 | cmd.append("print-" + makevar)
105 | pipe = subprocess.PIPE
106 | make = subprocess.Popen(cmd, stdout=pipe, stdin=pipe, stderr=pipe)
107 | printer = "print-%:\n\t@echo '$($*)'\n".encode("utf-8")
108 | output = make.communicate(input=printer)[0].decode("utf-8")
109 | tokens = []
110 | for line in output.split("\n"):
111 | if line:
112 | tokens += shlex.split(line)
113 | return Flag.tokenize_list(tokens, file.folder)
114 |
--------------------------------------------------------------------------------
/plugin/settings/__init__.py:
--------------------------------------------------------------------------------
1 | """Handle settings of the plugin."""
2 |
--------------------------------------------------------------------------------
/plugin/utils/__init__.py:
--------------------------------------------------------------------------------
1 | """Various utilities."""
2 |
--------------------------------------------------------------------------------
/plugin/utils/action_request.py:
--------------------------------------------------------------------------------
1 | """Encapsulates action request."""
2 | import logging
3 | log = logging.getLogger("ECC")
4 |
5 |
6 | class ActionRequest(object):
7 | """A wrapper for action request.
8 |
9 | Provides a way to identify an action request and provide some information
10 | used when creating the request.
11 | """
12 |
13 | def __init__(self, view, trigger_position):
14 | """Initialize the object.
15 |
16 | Args:
17 | view (sublime.View): The view for which request is created.
18 | trigger_position(int): The position for which request was created.
19 | """
20 | self._view = view
21 | self._trigger_position = trigger_position
22 |
23 | def get_view(self):
24 | """Return the view for which action was requested."""
25 | return self._view
26 |
27 | def get_trigger_position(self):
28 | """Get position of the trigger for which action was requested."""
29 | return self._trigger_position
30 |
31 | def get_identifier(self):
32 | """Generate unique tuple for file and trigger position."""
33 | return (self._view.buffer_id(), self._trigger_position)
34 |
35 | def is_suitable_for_view(self, view):
36 | """Check if view is suitable for this action request.
37 |
38 | Return True if specified view and its current position is deemed
39 | suitable for completions generated by this action request. """
40 | if view != self._view:
41 | log.debug("Active view doesn't match action view")
42 | return False
43 | # We accept both current position and position to the left of the
44 | # current word as valid as we don't know how much user already typed
45 | # after the trigger.
46 | current_position = view.sel()[0].a
47 | valid_positions = [current_position, view.word(current_position).a]
48 | if self._trigger_position not in valid_positions:
49 | log.debug("View's trigger positions %s doesn't match action "
50 | "trigger position %s",
51 | valid_positions,
52 | self._trigger_position)
53 | return False
54 | return True
55 |
--------------------------------------------------------------------------------
/plugin/utils/index_location.py:
--------------------------------------------------------------------------------
1 | """Class that mimics cursor.location for dealing with index locations."""
2 |
3 | from os import path
4 |
5 |
6 | class IndexLocation:
7 | """Location of a file that mimics Cursor.location."""
8 |
9 | class File:
10 | """Help class to mimic Cursor.file."""
11 |
12 | def __init__(self, name):
13 | """Initialize file name."""
14 | # 'name' is a bad name for a variable, but we need it to be this way
15 | # to conform with cursor.location.
16 | self.name = name
17 | self.extension = path.splitext(name)[1]
18 | self.short_name = path.basename(name)
19 |
20 | def __init__(self, filename, line, column):
21 | """Initialize new location."""
22 | self.file = IndexLocation.File(filename)
23 | self.line = line
24 | self.column = column
25 |
--------------------------------------------------------------------------------
/plugin/utils/macro_parser.py:
--------------------------------------------------------------------------------
1 | """Parse a macro from cindex."""
2 |
3 |
4 | class MacroParser(object):
5 | """Parse info from macros.
6 |
7 | Clang doesn't provide much information for MACRO_DEFINITION cursors,
8 | so we have to parse this info ourselves.
9 | """
10 |
11 | def __init__(self, name, location):
12 | """Parse the macro with the given name from its location.
13 |
14 | Args:
15 | name (str): Macro's name.
16 | location (cindex.SourceLocation): Macro definition's location.
17 | Can be None for unittests that parse with text content
18 | directly instead of loading from file.
19 |
20 | Future improvement: if there are line continuation characters
21 | in a macro with parenthesis, continue parsing into the next line
22 | to find it and create a proper args string.
23 | """
24 | self._args_string = ''
25 | self._name = name
26 | self._body = ''
27 | if location and location.file and location.file.name:
28 | with open(location.file.name, 'r', encoding='utf-8',
29 | errors='ignore') as f:
30 | macro_file_lines = f.readlines()
31 | self._parse_macro_file_lines(macro_file_lines, location.line)
32 |
33 | def _parse_macro_file_lines(self, macro_file_lines, macro_line_number):
34 | """Parse a macro from lines of text containing the macro.
35 |
36 | Args:
37 | macro_file_lines (list[str]): lines of text containing the macro
38 | macro_line_number (int): line number (1-based) of the macro
39 | in macro_file_lines.
40 | """
41 | macro_line = macro_file_lines[macro_line_number - 1].strip()
42 | # strip leading '#define'
43 | macro_line = macro_line.lstrip('#').lstrip().lstrip('define')
44 | macro_line = macro_line.lstrip().lstrip(self._name)
45 | # macro that looks like a function, possibly with args
46 | if macro_line.startswith('('):
47 | end_args_index = macro_line.find(')')
48 | # There should always be a closing parenthesis, but check
49 | # just in case a) the code is malformed or b) the macro
50 | # definition is continued on the next line so we can't
51 | # find it on this line.
52 | if end_args_index != -1:
53 | # If extra spaces, e.g. "#define MACRO( x , y , z )",
54 | # then flatten down to just "(x, y, z)"
55 | args_str = macro_line[1:end_args_index]
56 | args_str = ''.join(args_str.split())
57 | args_str = args_str.replace(',', ', ')
58 | self._args_string = '(' + args_str + ')'
59 | macro_line = macro_line[end_args_index + 1:]
60 |
61 | self._body = macro_line.strip()
62 | while self._body.endswith("\\"):
63 | macro_line_number += 1
64 | line = macro_file_lines[macro_line_number - 1].rstrip()
65 | self._body += "\n" + line
66 |
67 | @property
68 | def args_string(self):
69 | """Get arguments string.
70 |
71 | Examples:
72 | '#define MACRO()' would return '()'
73 | '#define MACRO(x, y)' would return '(x, y)'
74 | '#define MACRO' would return ''
75 | """
76 | return self._args_string
77 |
78 | @property
79 | def body_string(self):
80 | """Get macro body string."""
81 | return self._body
82 |
--------------------------------------------------------------------------------
/plugin/utils/module_reloader.py:
--------------------------------------------------------------------------------
1 | """A class needed to reload modules."""
2 | import sys
3 | import imp
4 | import logging
5 |
6 | from .tools import PKG_NAME
7 |
8 | log = logging.getLogger("ECC")
9 |
10 |
11 | class ModuleReloader:
12 | """Reloader for all dependencies."""
13 |
14 | MAX_RELOAD_TRIES = 10
15 |
16 | @staticmethod
17 | def reload_all(ignore_string='singleton'):
18 | """Reload all loaded modules."""
19 | prefix = PKG_NAME + '.plugin.'
20 | # reload all twice to make sure all dependencies are satisfied
21 | log.debug(
22 | "Reloading modules that start with '%s' and don't contain '%s'",
23 | prefix, ignore_string)
24 | log.debug("Reload all modules first time")
25 | ModuleReloader.reload_once(prefix, ignore_string)
26 | log.debug("Reload all modules second time")
27 | ModuleReloader.reload_once(prefix, ignore_string)
28 | log.debug("All modules reloaded")
29 |
30 | @staticmethod
31 | def reload_once(prefix, ignore_string):
32 | """Reload all modules once."""
33 | try_counter = 0
34 | try:
35 | for name, module in sys.modules.items():
36 | if name.startswith(prefix) and ignore_string not in name:
37 | log.debug("Reloading module: '%s'", name)
38 | imp.reload(module)
39 | except OSError as e:
40 | if try_counter >= ModuleReloader.MAX_RELOAD_TRIES:
41 | log.fatal("Too many tries to reload and no success. Fail.")
42 | return
43 | try_counter += 1
44 | log.error("Received an error: %s on try %s. Try again.",
45 | e, try_counter)
46 | ModuleReloader.reload_once(prefix, ignore_string)
47 |
--------------------------------------------------------------------------------
/plugin/utils/output_panel_handler.py:
--------------------------------------------------------------------------------
1 | """Handle everything related to the output panel."""
2 | import time
3 | import sublime
4 |
5 |
6 | class OutputPanelHandler():
7 | """Handle the output panel."""
8 | PANEL_TAG = "ECC"
9 | PANEL_NAME = "output." + PANEL_TAG
10 |
11 | @staticmethod
12 | def hide_panel():
13 | """Hide the output panel."""
14 | window = sublime.active_window()
15 | if window.active_panel() == OutputPanelHandler.PANEL_NAME:
16 | window.run_command(
17 | "hide_panel", {"panel": OutputPanelHandler.PANEL_NAME})
18 |
19 | @staticmethod
20 | def show(text):
21 | """Show the panel with text."""
22 | window = sublime.active_window()
23 | window.destroy_output_panel(OutputPanelHandler.PANEL_TAG)
24 | panel_view = window.create_output_panel(
25 | OutputPanelHandler.PANEL_TAG)
26 | while panel_view.is_loading():
27 | time.sleep(0.1)
28 | panel_view.run_command("select_all")
29 | panel_view.run_command("right_delete")
30 |
31 | settings = panel_view.settings()
32 | settings.set("tab_size", 0)
33 | settings.set("line_numbers", True)
34 | panel_view.run_command("insert", {"characters": text})
35 | panel_view.sel().clear()
36 | panel_view.show(panel_view.size())
37 |
38 | window.run_command(
39 | "show_panel", {"panel": OutputPanelHandler.PANEL_NAME})
40 | panel_view.set_read_only(True)
41 |
--------------------------------------------------------------------------------
/plugin/utils/progress_status.py:
--------------------------------------------------------------------------------
1 | """Module for progress status indicator.
2 |
3 | Attributes:
4 | MSG_CHARS_COLOR_SUBLIME: chars for using in colorsublime-like progress
5 | MSG_READY_COLOR_SUBLIME: ready message in colorsublime-like progress
6 | MSG_CHARS_MOON (str): chars for using in moon-like progress
7 | MSG_READY_MOON (str): ready message in moon-like progress
8 | """
9 |
10 | import sublime
11 |
12 | MSG_CHARS_MOON = u'🌑🌒🌓🌔🌕🌖🌗🌘'
13 | MSG_READY_MOON = u'✔'
14 | MSG_CHARS_COLOR_SUBLIME = u'⣾⣽⣻⢿⡿⣟⣯⣷'
15 | MSG_READY_COLOR_SUBLIME = ' READY '
16 |
17 |
18 | class BaseProgressStatus(object):
19 | """A base class for progress status."""
20 |
21 | MSG_TAG = '000_ECC'
22 | MSG_MASK = ' | {msg} |'
23 | PROGRESS_MASK = 'ECC: [{progress}]'
24 | FULL_MASK = PROGRESS_MASK + MSG_MASK
25 |
26 | def __init__(self):
27 | """Initialize progress status."""
28 | self.showing = False
29 | self.msg_chars = None
30 | self.msg_ready = None
31 |
32 | @staticmethod
33 | def set_status(message):
34 | """Set status message for the current view."""
35 | view = sublime.active_window().active_view()
36 | view.set_status(BaseProgressStatus.MSG_TAG, message)
37 |
38 | def erase_status(self):
39 | """Erase status message for the current view."""
40 | self.showing = False
41 | view = sublime.active_window().active_view()
42 | view.erase_status(BaseProgressStatus.MSG_TAG)
43 |
44 | def show_as_ready(self):
45 | """Show ready state."""
46 | if not self.showing:
47 | return
48 | BaseProgressStatus.set_status(
49 | BaseProgressStatus.PROGRESS_MASK.format(progress=self.msg_ready))
50 |
51 | def update_progress(self, message=''):
52 | """Abstract method. Generate next message."""
53 | raise NotImplementedError("abstract method is called")
54 |
55 |
56 | class MoonProgressStatus(BaseProgressStatus):
57 | """Progress status that shows phases of the moon."""
58 |
59 | def __init__(self):
60 | """Init moon progress status."""
61 | super().__init__()
62 | self.idx = 0
63 | self.msg_chars = MSG_CHARS_MOON
64 | self.msg_ready = MSG_READY_MOON
65 |
66 | def update_progress(self, message):
67 | """Show next moon phase and a custom message."""
68 | if not self.showing:
69 | return
70 | chars = self.msg_chars
71 | mod = len(chars)
72 | self.idx = (self.idx + 1) % mod
73 | BaseProgressStatus.set_status(
74 | BaseProgressStatus.FULL_MASK.format(
75 | progress=chars[self.idx], msg=message))
76 |
77 |
78 | class ColorSublimeProgressStatus(BaseProgressStatus):
79 | """Progress status that shows phases of the moon."""
80 |
81 | def __init__(self):
82 | """Init color sublime like progress status."""
83 | super().__init__()
84 | self.msg_chars = MSG_CHARS_COLOR_SUBLIME
85 | self.msg_ready = MSG_READY_COLOR_SUBLIME
86 |
87 | def update_progress(self, message):
88 | """Show next random progress indicator and a custom message."""
89 | if not self.showing:
90 | return
91 | from random import sample
92 | mod = len(self.msg_chars)
93 | rands = [self.msg_chars[x % mod] for x in sample(range(100), 10)]
94 | BaseProgressStatus.set_status(
95 | BaseProgressStatus.FULL_MASK.format(
96 | progress=''.join(rands), msg=message))
97 |
98 |
99 | class NoneSublimeProgressStatus(BaseProgressStatus):
100 | """Progress status that does nothing."""
101 |
102 | def __init__(self):
103 | """Init color sublime like progress status."""
104 | super().__init__()
105 | self.showing = False
106 |
107 | def show_as_ready(self):
108 | """Empty implementation."""
109 | pass
110 |
111 | def update_progress(self, message):
112 | """Empty implementation."""
113 | pass
114 |
--------------------------------------------------------------------------------
/plugin/utils/quick_panel_handler.py:
--------------------------------------------------------------------------------
1 | """Host a class that controls the way we interact with quick pannel."""
2 |
3 | import logging
4 | import sublime
5 |
6 | from ..error_vis.popup_error_vis import MIN_ERROR_SEVERITY
7 |
8 | log = logging.getLogger("ECC")
9 |
10 |
11 | class ErrorQuickPanelHandler():
12 | """Handle the quick panel."""
13 |
14 | ENTRY_TEMPLATE = "{type}: {error}"
15 |
16 | def __init__(self, view, errors):
17 | """Initialize the object.
18 |
19 | Args:
20 | view (sublime.View): Current view.
21 | errors (list(dict)): A list of error dicts.
22 | """
23 | self.view = view
24 | self.errors = errors
25 |
26 | def items_to_show(self):
27 | """Present errors as list of lists."""
28 | contents = []
29 | for error_dict in self.errors:
30 | error_type = 'ERROR'
31 | if error_dict['severity'] < MIN_ERROR_SEVERITY:
32 | error_type = 'WARNING'
33 | contents.append(
34 | [
35 | ErrorQuickPanelHandler.ENTRY_TEMPLATE.format(
36 | type=error_type,
37 | error=error_dict['error']),
38 | error_dict['file']
39 | ])
40 | return contents
41 |
42 | def on_done(self, idx):
43 | """Pick this error to navigate to a file."""
44 | log.debug("Picked idx: %s", idx)
45 | if idx < 0 or idx >= len(self.errors):
46 | return None
47 | return self.view.window().open_file(self.__get_formatted_location(idx),
48 | sublime.ENCODED_POSITION)
49 |
50 | def __get_formatted_location(self, idx):
51 | picked_entry = self.errors[idx]
52 | return "{file}:{row}:{col}".format(file=picked_entry['file'],
53 | row=picked_entry['row'],
54 | col=picked_entry['col'])
55 |
56 | def show(self, window):
57 | """Show the quick panel."""
58 | start_idx = 0
59 | window.show_quick_panel(
60 | self.items_to_show(),
61 | self.on_done,
62 | sublime.MONOSPACE_FONT,
63 | start_idx)
64 |
--------------------------------------------------------------------------------
/plugin/utils/search_scope.py:
--------------------------------------------------------------------------------
1 | """Defines all search scopes used in this project."""
2 | from os import path
3 |
4 | ROOT_PATH = path.abspath('/')
5 |
6 |
7 | class TreeSearchScope:
8 | """Encapsulation of a search scope to search up the tree."""
9 |
10 | def __init__(self,
11 | from_folder=ROOT_PATH,
12 | to_folder=ROOT_PATH):
13 | """Initialize the search scope."""
14 | self.from_folder = from_folder
15 | self.to_folder = to_folder
16 |
17 | @property
18 | def from_folder(self):
19 | """Get the starting folder."""
20 | return self._from_folder
21 |
22 | @from_folder.setter
23 | def from_folder(self, folder):
24 | """Set the last folder in search."""
25 | self._from_folder = folder
26 | self._current_folder = self._from_folder
27 |
28 | @property
29 | def to_folder(self):
30 | """Get the end of search folder."""
31 | return self._to_folder
32 |
33 | @to_folder.setter
34 | def to_folder(self, folder):
35 | """Set the last folder in search."""
36 | self._to_folder = folder
37 | self._one_past_last = path.dirname(self._to_folder)
38 |
39 | def __bool__(self):
40 | """Check if the search scope is empty."""
41 | return self.from_folder != ROOT_PATH
42 |
43 | def __iter__(self):
44 | """Make this an iterator."""
45 | self._current_folder = self._from_folder
46 | return self
47 |
48 | def __next__(self):
49 | """Get next folder to search in."""
50 | current_folder = self._current_folder
51 | self._current_folder = path.dirname(self._current_folder)
52 | scope_end_reached = current_folder == self._one_past_last
53 | root_reached = current_folder == self._current_folder
54 | if root_reached or scope_end_reached:
55 | raise StopIteration
56 | else:
57 | return current_folder
58 |
59 | def __repr__(self):
60 | """Return search scope as a printable string."""
61 | return 'SearchScope: from_folder: {}, to_folder: {}'.format(
62 | self._from_folder, self._to_folder)
63 |
64 |
65 | class ListSearchScope:
66 | """Encapsulation of a search scope to search in a list."""
67 |
68 | def __init__(self, paths=[]):
69 | """Initialize the search scope."""
70 | self.folders = paths
71 |
72 | @property
73 | def folders(self):
74 | """Get the starting folder."""
75 | return self._folders
76 |
77 | @folders.setter
78 | def folders(self, paths):
79 | """Set the folders."""
80 | self._folders = [f for f in paths if path.isdir(f)]
81 | self._iter = iter(self._folders)
82 |
83 | def __bool__(self):
84 | """Check if the search scope is not empty."""
85 | return len(self._folders) > 0
86 |
87 | def __iter__(self):
88 | """Make this an iterator."""
89 | self._iter = iter(self._folders)
90 | return self._iter
91 |
92 | def __next__(self):
93 | """Get next folder to search in."""
94 | return next(self._iter)
95 |
96 | def __repr__(self):
97 | """Return search scope as a printable string."""
98 | return 'SearchScope: folders: {}'.format(self._folders)
99 |
--------------------------------------------------------------------------------
/plugin/utils/singleton.py:
--------------------------------------------------------------------------------
1 | """Singleton related stuff. Should only be imported ONCE."""
2 |
3 |
4 | def singleton(class_):
5 | """Singleton class wrapper.
6 |
7 | Args:
8 | class_ (Class): Class to wrap.
9 |
10 | Returns:
11 | class_: unique instance of object.
12 | """
13 | instances = {}
14 |
15 | def getinstance(*args, **kwargs):
16 | """Get instance of a class."""
17 | if class_ not in instances:
18 | instances[class_] = class_(*args, **kwargs)
19 | return instances[class_]
20 | return getinstance
21 |
22 | # ALL the singletons used throughout the codebase go below this line:
23 | ##############################################################################
24 | ##############################################################################
25 | ##############################################################################
26 |
27 |
28 | @singleton
29 | class ViewConfigCache(dict):
30 | """Singleton for view configurations cache."""
31 | pass
32 |
33 |
34 | @singleton
35 | class CppPropertiesCache(dict):
36 | """Singleton for CppProperties.json file cache."""
37 | pass
38 |
39 |
40 | @singleton
41 | class CCppPropertiesCache(dict):
42 | """Singleton for c_cpp_properties.json file cache."""
43 | pass
44 |
45 |
46 | @singleton
47 | class CMakeFileCache(dict):
48 | """Singleton for CMakeLists.txt file cache."""
49 | pass
50 |
51 |
52 | @singleton
53 | class MakefileCache(dict):
54 | """Singleton for Makefile file cache."""
55 | pass
56 |
57 |
58 | @singleton
59 | class ComplationDbCache(dict):
60 | """Singleton for compilation database cache."""
61 | pass
62 |
63 |
64 | @singleton
65 | class ThreadCache(dict):
66 | """Singleton for a cache of running threads."""
67 | pass
68 |
69 |
70 | @singleton
71 | class FlagsFileCache(dict):
72 | """Singleton for .clang_fomplete file cache."""
73 | pass
74 |
75 |
76 | class GenericCache:
77 | """A class to be able to import the function below."""
78 | @staticmethod
79 | def clear_all_caches():
80 | """Clear all existing caches."""
81 | CCppPropertiesCache().clear()
82 | CMakeFileCache().clear()
83 | MakefileCache().clear()
84 | ComplationDbCache().clear()
85 | CppPropertiesCache().clear()
86 | FlagsFileCache().clear()
87 | ViewConfigCache().clear()
88 | ThreadCache().clear()
89 |
--------------------------------------------------------------------------------
/plugin/utils/subl/row_col.py:
--------------------------------------------------------------------------------
1 | """Represent different ways to work with row and column in views."""
2 |
3 |
4 | class ZeroIndexedRowCol():
5 | """A cursor position as 0-indexed row and column."""
6 |
7 | def __init__(self, row, col):
8 | """Initialize from row and column as seen in file (start with 1)."""
9 | self._row = row
10 | self._col = col
11 |
12 | @property
13 | def row(self):
14 | """Return row."""
15 | return self._row
16 |
17 | @property
18 | def col(self):
19 | """Return col."""
20 | return self._col
21 |
22 | def as_1d_location(self, view):
23 | """Return the cursor position as 1d location in a view."""
24 | return view.text_point(self._row, self._col)
25 |
26 | @staticmethod
27 | def from_one_indexed(one_indexed_row_col):
28 | """Convert 1-indexed row column into the 0-indexed representation."""
29 | return ZeroIndexedRowCol(one_indexed_row_col._row - 1,
30 | one_indexed_row_col._col - 1)
31 |
32 | @staticmethod
33 | def from_1d_location(view, pos):
34 | """Get row and column from a 1d location in a view."""
35 | if pos is None:
36 | return ZeroIndexedRowCol.from_current_cursor_pos(view)
37 | row, col = view.rowcol(pos)
38 | return ZeroIndexedRowCol(row, col)
39 |
40 | @classmethod
41 | def from_current_cursor_pos(cls, view):
42 | """Generate row and columg from current cursor position in view."""
43 | pos = view.sel()
44 | if pos is None or len(pos) < 1:
45 | # something is wrong
46 | return None
47 | # We care about the first position only.
48 | pos = pos[0].a
49 | return cls.from_1d_location(view, pos)
50 |
51 | def as_tuple(self):
52 | """Return as tuple."""
53 | return (self._row, self._col)
54 |
55 |
56 | class OneIndexedRowCol():
57 | """Stores a cursor position."""
58 |
59 | def __init__(self, row, col):
60 | """Initialize from a zero-indexed row and column."""
61 | self._row = row
62 | self._col = col
63 |
64 | @staticmethod
65 | def from_zero_indexed(zero_indexed_row_col):
66 | """Convert 0-indexed row column into the 1-indexed representation."""
67 | return ZeroIndexedRowCol(zero_indexed_row_col._row + 1,
68 | zero_indexed_row_col._col + 1)
69 |
70 | @property
71 | def row(self):
72 | """Return row."""
73 | return self._row
74 |
75 | @property
76 | def col(self):
77 | """Return col."""
78 | return self._col
79 |
80 | def as_tuple(self):
81 | """Return as tuple."""
82 | return (self._row, self._col)
83 |
--------------------------------------------------------------------------------
/plugin/utils/thread_job.py:
--------------------------------------------------------------------------------
1 | """Class that defined a job to be run in a thread pool.
2 |
3 | Attributes:
4 | log (logging.Logger): Logger for current module.
5 | """
6 | import logging
7 |
8 |
9 | log = logging.getLogger("ECC")
10 |
11 |
12 | class ThreadJob:
13 | """A class for a job that can be submitted to ThreadPool.
14 |
15 | Attributes:
16 | name (str): Name of this job.
17 | callback (func): Function to use as callback.
18 | function (func): Function to run asynchronously.
19 | args (object[]): Sequence of additional arguments for `function`.
20 | """
21 |
22 | UPDATE_TAG = "Updating translation unit"
23 | CLEAR_TAG = "Clearing"
24 | COMPLETE_TAG = "Completing"
25 | COMPLETE_INCLUDES_TAG = "Competing includes"
26 | GENERATE_DB_TAG = "Generating compilation database"
27 | INFO_TAG = "Showing info"
28 |
29 | def __init__(self, name, callback, function, args):
30 | """Initialize a job.
31 |
32 | Args:
33 | name (str): Name of this job.
34 | callback (func): Function to use as callback.
35 | function (func): Function to run asynchronously.
36 | args (object[]): Sequence of additional arguments for `function`.
37 | future (future): A future that tracks the execution of this job.
38 | """
39 | self.name = name
40 | self.callback = callback
41 | self.function = function
42 | self.args = args
43 | self.future = None
44 |
45 | def is_high_priority(self):
46 | """Check if job is high priority."""
47 | return self.name in [ThreadJob.UPDATE_TAG,
48 | ThreadJob.CLEAR_TAG,
49 | ThreadJob.GENERATE_DB_TAG]
50 |
51 | def __repr__(self):
52 | """Representation."""
53 | return "job: '{name}'".format(name=self.name)
54 |
55 | def overrides(self, other):
56 | """Define if one job overrides another."""
57 | if self.is_same_type_as(other):
58 | return True
59 | if self.is_high_priority() and not other.is_high_priority():
60 | return True
61 | return False
62 |
63 | def is_same_type_as(self, other):
64 | """Define if these are the same type of jobs."""
65 | return self.name == other.name
66 |
--------------------------------------------------------------------------------
/plugin/utils/tools.py:
--------------------------------------------------------------------------------
1 | """Collection of various tools."""
2 | from os import path
3 | from os import environ
4 |
5 | import sublime
6 | import logging
7 | import subprocess
8 |
9 |
10 | PKG_NAME = path.basename(path.dirname(path.dirname(path.dirname(__file__))))
11 | PKG_FOLDER = path.dirname(path.dirname(path.dirname(__file__)))
12 |
13 | _log = logging.getLogger("ECC")
14 |
15 |
16 | class Tools:
17 | """Just a bunch of helpful tools."""
18 |
19 | @staticmethod
20 | def seconds_from_string(time_str):
21 | """Get int seconds from string.
22 |
23 | Args:
24 | time_str (str): string in format 'HH:MM:SS'
25 |
26 | Returns:
27 | int: seconds
28 | """
29 | h, m, s = time_str.split(":")
30 | return int(h) * 3600 + int(m) * 60 + int(s)
31 |
32 | @staticmethod
33 | def run_command(command, shell=False, cwd=path.curdir, env=environ,
34 | stdin=None, default=None):
35 | """Run a generic command in a subprocess.
36 |
37 | Args:
38 | command (str): command to run
39 | stdin: The standard input channel for the started process.
40 | default (andy): The default return value in case run fails.
41 |
42 | Returns:
43 | str: raw command output or default value
44 | """
45 | output_text = default
46 | try:
47 | startupinfo = None
48 | if sublime.platform() == "windows":
49 | # Don't let console window pop-up briefly.
50 | startupinfo = subprocess.STARTUPINFO()
51 | startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
52 | startupinfo.wShowWindow = subprocess.SW_HIDE
53 | if stdin is None:
54 | stdin = subprocess.PIPE
55 | output = subprocess.check_output(command,
56 | stdin=stdin,
57 | stderr=subprocess.STDOUT,
58 | shell=shell,
59 | cwd=cwd,
60 | env=env,
61 | startupinfo=startupinfo)
62 | output_text = ''.join(map(chr, output))
63 | except subprocess.CalledProcessError as e:
64 | output_text = e.output.decode("utf-8")
65 | _log.debug("Command finished with code: %s", e.returncode)
66 | _log.debug("Command output: \n%s", output_text)
67 | except OSError:
68 | _log.debug(
69 | "Executable file not found executing: {}".format(command))
70 | return output_text
71 |
72 | @staticmethod
73 | def get_unique_str(init_string):
74 | """Generate md5 unique sting hash given init_string."""
75 | import hashlib
76 | augmented_string = init_string + path.expanduser('~')
77 | return hashlib.md5(augmented_string.encode('utf-8')).hexdigest()
78 |
--------------------------------------------------------------------------------
/plugin/utils/unique_list.py:
--------------------------------------------------------------------------------
1 | """Encapsulates set augmented list with unique stored values."""
2 |
3 |
4 | class UniqueList:
5 | """A list that guarantees unique insertion."""
6 |
7 | def __init__(self, other=None):
8 | """Init with another iterable if it is present."""
9 | self.__values = list()
10 | self.__values_set = set()
11 | if not other:
12 | return
13 | for value in other:
14 | self.append(value)
15 |
16 | def append(self, value):
17 | """Append a single value.
18 |
19 | Args:
20 | value: input value
21 | """
22 | if value not in self.__values_set:
23 | self.__values.append(value)
24 | self.__values_set.add(value)
25 |
26 | def as_list(self):
27 | """Return an ordinary python list."""
28 | return self.__values
29 |
30 | def clear(self):
31 | """Clear the list."""
32 | self.__values = list()
33 | self.__values_set = set()
34 |
35 | def __add__(self, other):
36 | """Append another iterable.
37 |
38 | Args:
39 | other (iterable): some other iterable container
40 | Returns:
41 | UniqueList: new list with appended elements
42 | """
43 | for value in other:
44 | self.append(value)
45 | return self
46 |
47 | def __iter__(self):
48 | """Make iterable."""
49 | return iter(self.__values)
50 |
51 | def __str__(self):
52 | """Make convertable to str."""
53 | return str(self.__values)
54 |
--------------------------------------------------------------------------------
/plugin/view_config/__init__.py:
--------------------------------------------------------------------------------
1 | """View config and things related to it."""
2 |
--------------------------------------------------------------------------------
/tests/CppProperties_files/empty/CppProperties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "includePath": [
5 | ],
6 | "intelliSenseMode": "msvc-x64",
7 | "name": "waf_build_tree"
8 | }
9 | ]
10 | }
--------------------------------------------------------------------------------
/tests/CppProperties_files/environment/CppProperties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "includePath": [
5 | "${env.TEST_VARIABLE_TO_EXPAND}"
6 | ],
7 | "intelliSenseMode": "msvc-x64",
8 | "name": "waf_build_tree"
9 | }
10 | ]
11 | }
--------------------------------------------------------------------------------
/tests/CppProperties_files/simple/CppProperties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "includePath": [
5 | "/folder/include/path",
6 | "/another/file/path"
7 | ],
8 | "intelliSenseMode": "msvc-x64",
9 | "name": "waf_build_tree"
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 | """Tests of ECC."""
2 |
--------------------------------------------------------------------------------
/tests/bazel/bad_project/WORKSPACE:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/tests/bazel/bad_project/WORKSPACE
--------------------------------------------------------------------------------
/tests/bazel/bad_project/app/BUILD:
--------------------------------------------------------------------------------
1 | cc_binary(
2 | name = "main"
3 | srcs = ["main.cpp"],
4 | )
5 |
--------------------------------------------------------------------------------
/tests/bazel/bad_project/app/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main(int argc, char const *argv[]) {
4 | std::vector vec;
5 | vec.push_back(10);
6 | return 0;
7 | }
8 |
--------------------------------------------------------------------------------
/tests/bazel/good_project/WORKSPACE:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niosus/EasyClangComplete/49cfb0325297752a900b072a64282f94f2a021f8/tests/bazel/good_project/WORKSPACE
--------------------------------------------------------------------------------
/tests/bazel/good_project/app/BUILD:
--------------------------------------------------------------------------------
1 | cc_binary(
2 | name = "main",
3 | srcs = ["main.cpp"],
4 | )
5 |
--------------------------------------------------------------------------------
/tests/bazel/good_project/app/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | int main(int argc, char const *argv[]) {
4 | std::vector vec;
5 | vec.push_back(10);
6 | return 0;
7 | }
8 |
--------------------------------------------------------------------------------
/tests/c_cpp_properties_files/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Win32",
5 | "intelliSenseMode": "msvc-x64",
6 | "includePath": [ "${workspaceRoot}" ],
7 | "defines": [ "FOO", "BAR=100" ],
8 | "compileCommands": "/path/to/compile_commands.json",
9 | "browse": {
10 | "path": [ "${workspaceRoot}" ],
11 | "limitSymbolsToIncludedHeaders": true,
12 | "databaseFilename": ""
13 | }
14 | }
15 | ],
16 | "version": 2
17 | }
--------------------------------------------------------------------------------
/tests/c_cpp_properties_files/empty/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Win32",
5 | "intelliSenseMode": "msvc-x64",
6 | "includePath": [],
7 | "defines": [],
8 | "compileCommands": "/path/to/compile_commands.json",
9 | "browse": {
10 | "path": [ "${workspaceRoot}" ],
11 | "limitSymbolsToIncludedHeaders": true,
12 | "databaseFilename": ""
13 | }
14 | }
15 | ],
16 | "version": 2
17 | }
--------------------------------------------------------------------------------
/tests/c_cpp_properties_files/environment/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Win32",
5 | "intelliSenseMode": "msvc-x64",
6 | "includePath": [ "${TEST_VARIABLE_TO_EXPAND}" ],
7 | "defines": [ "lib_EXPORTS" ],
8 | "compileCommands": "/path/to/compile_commands.json",
9 | "browse": {
10 | "path": [ "${workspaceRoot}" ],
11 | "limitSymbolsToIncludedHeaders": true,
12 | "databaseFilename": ""
13 | }
14 | }
15 | ],
16 | "version": 2
17 | }
--------------------------------------------------------------------------------
/tests/c_cpp_properties_files/simple/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Win32",
5 | "intelliSenseMode": "msvc-x64",
6 | "includePath": [ "/lib_include_dir" ],
7 | "defines": [ "lib_EXPORTS" ],
8 | "compileCommands": "/path/to/compile_commands.json",
9 | "browse": {
10 | "path": [ "${workspaceRoot}" ],
11 | "limitSymbolsToIncludedHeaders": true,
12 | "databaseFilename": ""
13 | }
14 | }
15 | ],
16 | "version": 2
17 | }
--------------------------------------------------------------------------------
/tests/catkin_tests/catkin_ws/src/project/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | project(catkin_test)
2 | cmake_minimum_required(VERSION 3.0)
3 |
4 | find_package(catkin)
5 |
6 | add_executable(main main.cpp)
7 |
--------------------------------------------------------------------------------
/tests/catkin_tests/catkin_ws/src/project/main.cpp:
--------------------------------------------------------------------------------
1 | // Copyright Igor Bogoslavskyi, year 2018.
2 | // In case of any problems with the code please contact me.
3 |
4 | int main(int argc, char const *argv[]) { return 0; }
5 |
--------------------------------------------------------------------------------
/tests/cmake_tests/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8)
2 |
3 | project (test_cmake_project)
4 |
5 | add_subdirectory(lib)
6 | include_directories(lib)
7 |
8 | add_executable(test_a test_a.cpp)
9 | target_link_libraries(test_a liba)
10 |
--------------------------------------------------------------------------------
/tests/cmake_tests/lib/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_library(liba SHARED a.cpp)
2 |
--------------------------------------------------------------------------------
/tests/cmake_tests/lib/a.cpp:
--------------------------------------------------------------------------------
1 | #include "a.h"
2 |
3 | #include
4 |
5 | void A::foo(int bar) { fprintf(stderr, "hello: %d\n", bar); }
6 |
--------------------------------------------------------------------------------
/tests/cmake_tests/lib/a.h:
--------------------------------------------------------------------------------
1 | struct A {
2 | int bar;
3 | void foo(int bar);
4 | };
5 |
--------------------------------------------------------------------------------
/tests/cmake_tests/test_a.cpp:
--------------------------------------------------------------------------------
1 | #include "a.h"
2 |
3 | int main(int argc, char const *argv[]) {
4 | A a;
5 | a.foo(10);
6 | return 0;
7 | }
8 |
--------------------------------------------------------------------------------
/tests/compilation_db_files/arguments/compile_commands.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "arguments": [
4 | "c++",
5 | "-I/lib_include_dir",
6 | "-o",
7 | "CMakeFiles/main_obj.o",
8 | "-c",
9 | "/home/user/dummy_main.cpp"
10 | ],
11 | "directory": "/main_dir",
12 | "file": "/home/user/dummy_main.cpp"
13 | },
14 | {
15 | "arguments": [
16 | "c++",
17 | "-Dlib_EXPORTS",
18 | "-fPIC",
19 | "-o",
20 | "CMakeFiles/lib_obj.o",
21 | "-c",
22 | "/home/user/dummy_lib.cpp"
23 | ],
24 | "directory": "/lib_dir",
25 | "file": "/home/user/dummy_lib.cpp"
26 | }
27 | ]
28 |
--------------------------------------------------------------------------------
/tests/compilation_db_files/command/compile_commands.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "directory": "/main_dir",
4 | "command": "c++ -I/lib_include_dir -o CMakeFiles/main_obj.o -c /home/user/dummy_main.cpp",
5 | "file": "/home/user/dummy_main.cpp"
6 | },
7 | {
8 | "directory": "/lib_dir",
9 | "command": "c++ -Dlib_EXPORTS -fPIC -o CMakeFiles/lib_obj.o -c /home/user/dummy_lib.cpp",
10 | "file": "/home/user/dummy_lib.cpp"
11 | }
12 | ]
13 |
--------------------------------------------------------------------------------
/tests/compilation_db_files/command_c/compile_commands.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "command": "cc -c -I/home/blah/clients -I/home/blah -I/home/blah/core/h -I/home/blah/network/h -I/home/blah/update/h -I/home/blah/h -I/home/blah/h -I/usr/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libsoup-2.4 -I/usr/include/libxml2 -I/usr/include -I/platform/include/fd655 -I/platform/include/ct1628 -I/home/blah/h -I/home/blah/fs/h -I/home/blah/network/h -I/home/blah/update/h -I/home/blah/update/h -Wall -Wno-unused-function -D_REENTRANT -DWITH_THREADS=1 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fgnu89-inline -fPIC -D_ALI_BUILD_ -D_GNU_SOURCE -shared-libgcc -std=gnu99 -march=armv7-a -mtune=cortex-a9 -DARMV7SP -ggdb -O2 -Werror -DDEVELOP -o -mfpu=vfp3 -mfloat-abi=softfp -mtune=cortex-a9 -march=armv7-a -Wno-poison-system-directories /home/blah/c/blah.c",
4 | "directory": "/home/blah",
5 | "file": "/home/blah.c"
6 | }
7 | ]
8 |
--------------------------------------------------------------------------------
/tests/compilation_db_files/command_c_ccache/compile_commands.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "command": "ccache cc -c -I/home/blah/clients -I/home/blah -I/home/blah/core/h -I/home/blah/network/h -I/home/blah/update/h -I/home/blah/h -I/home/blah/h -I/usr/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libsoup-2.4 -I/usr/include/libxml2 -I/usr/include -I/platform/include/fd655 -I/platform/include/ct1628 -I/home/blah/h -I/home/blah/fs/h -I/home/blah/network/h -I/home/blah/update/h -I/home/blah/update/h -Wall -Wno-unused-function -D_REENTRANT -DWITH_THREADS=1 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fgnu89-inline -fPIC -D_ALI_BUILD_ -D_GNU_SOURCE -shared-libgcc -std=gnu99 -march=armv7-a -mtune=cortex-a9 -DARMV7SP -ggdb -O2 -Werror -DDEVELOP -o -mfpu=vfp3 -mfloat-abi=softfp -mtune=cortex-a9 -march=armv7-a -Wno-poison-system-directories /home/blah/c/blah.c",
4 | "directory": "/home/blah",
5 | "file": "/home/blah.c"
6 | }
7 | ]
8 |
--------------------------------------------------------------------------------
/tests/compilation_db_files/command_c_ccache_irrelevant/compile_commands.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "command": "cc -c -I/home/blah/clients -I/home/blah -I/home/blah/core/h -I/home/blah/network/h -I/home/blah/update/h -I/home/blah/h -I/home/blah/h -I/usr/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libsoup-2.4 -I/usr/include/libxml2 -I/usr/include -I/platform/include/fd655 -I/platform/include/ct1628 -I/home/blah/h -I/home/blah/fs/h -I/home/blah/network/h -I/home/blah/update/h -I/home/blah/update/h -Wall -Wno-unused-function -D_REENTRANT -DWITH_THREADS=1 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fgnu89-inline -fPIC -D_ALI_BUILD_ -D_GNU_SOURCE -shared-libgcc -std=gnu99 -march=armv7-a -mtune=cortex-a9 -DARMV7SP -ggdb -O2 -Werror -DDEVELOP -o -mfpu=vfp3 -mfloat-abi=softfp -mtune=cortex-a9 -march=armv7-a -Wno-poison-system-directories ccache",
4 | "directory": "/home/blah",
5 | "file": "/home/blah.c"
6 | }
7 | ]
8 |
--------------------------------------------------------------------------------
/tests/compilation_db_files/directory/compile_commands.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "arguments": [
4 | "c++",
5 | "-I./include",
6 | "-I../../include",
7 | "-isystem",
8 | "../matilda",
9 | "test.cpp"
10 | ],
11 | "directory": "/foo/bar/test",
12 | "file": "test.cpp"
13 | }
14 | ]
15 |
--------------------------------------------------------------------------------
/tests/gui_test_wrapper.py:
--------------------------------------------------------------------------------
1 | """Tests for cmake database generation."""
2 | import sublime
3 | import time
4 | from unittest import TestCase
5 |
6 | from EasyClangComplete.plugin.utils.tools import PKG_NAME
7 |
8 |
9 | class GuiTestWrapper(TestCase):
10 | """A class that makes gui tests easier.
11 |
12 | Attributes:
13 | view (sublime.View): Current view.
14 | """
15 |
16 | def setUp(self):
17 | """Prepare the view every run."""
18 | # Ensure we have a window to work with.
19 | s = sublime.load_settings("Preferences.sublime-settings")
20 | s.set("close_windows_when_empty", False)
21 | s = sublime.load_settings(PKG_NAME + ".sublime-settings")
22 | s.set("verbose", True)
23 | s.set("cmake_flags_priority", "overwrite")
24 | self.view = None
25 |
26 | def tearDown(self):
27 | """Cleanup method run after every test."""
28 | # If we have a view, close it.
29 | if self.view:
30 | self.view.set_scratch(True)
31 | self.view.window().focus_view(self.view)
32 | self.view.window().run_command("close_file")
33 | self.view = None
34 |
35 | def set_up_view(self, file_path=None, cursor_position=None):
36 | """Open the view and wait until its open.
37 |
38 | Args:
39 | file_path (str): The path to a file to open in a new view.
40 | cursor_position (ZeroIndexedRowCol): row and column of the cursor.
41 | """
42 | # Open the view.
43 | if file_path:
44 | self.view = sublime.active_window().open_file(file_path)
45 | else:
46 | self.view = sublime.active_window().new_file()
47 | self.view.settings().set("disable_easy_clang_complete", True)
48 |
49 | # Ensure it's loaded.
50 | while self.view.is_loading():
51 | time.sleep(0.1)
52 |
53 | if cursor_position:
54 | self.view.sel().clear()
55 | self.view.sel().add(
56 | sublime.Region(cursor_position.as_1d_location(self.view)))
57 |
58 | def get_row(self, row):
59 | """Get text of a particular row.
60 |
61 | Args:
62 | row (int): number of row
63 |
64 | Returns:
65 | str: row contents
66 | """
67 | return self.view.substr(self.view.line(self.view.text_point(row, 0)))
68 |
69 | def check_view(self, file_path):
70 | """Test that setup view correctly sets up the view."""
71 | self.set_up_view(file_path)
72 |
73 | self.assertEqual(self.view.file_name(), file_path)
74 | file = open(file_path, 'r')
75 | row = 0
76 | line = file.readline()
77 | while line:
78 | self.assertEqual(line[:-1], self.get_row(row))
79 | row += 1
80 | line = file.readline()
81 | file.close()
82 |
--------------------------------------------------------------------------------
/tests/makefile_files/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.a
3 | /app
4 |
--------------------------------------------------------------------------------
/tests/makefile_files/Makefile:
--------------------------------------------------------------------------------
1 | INCLUDES = -Iinc
2 | CPPFLAGS = -DREQUIRED_DEFINE
3 | CC = clang
4 |
5 | app : main.c inc/bar.h
6 | $(MAKE) -C lib
7 | $(CC) $(INCLUDES) $(CPPFLAGS) -o $@ main.c lib/libbar.a
8 |
9 | clean :
10 | $(MAKE) -C lib clean
11 | rm app
12 |
--------------------------------------------------------------------------------
/tests/makefile_files/inc/bar.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef REQUIRED_DEFINE
3 | # error missing required define
4 | #endif
5 |
6 | int bar(const char *str);
7 |
--------------------------------------------------------------------------------
/tests/makefile_files/lib/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS = -Ifoo
2 | CPPFLAGS = -DREQUIRED_DEFINE
3 | CC = clang
4 | AR = ar
5 |
6 | libbar.a : bar.o foo.o
7 | $(AR) rcs $@ $?
8 |
9 | foo.o : foo/foo.h foo/foo.c
10 | $(CC) $(CFLAGS) -c -o $@ foo/foo.c
11 |
12 | bar.o : bar.c
13 | $(CC) $(CFLAGS) -c -o $@ bar.c
14 |
15 | clean :
16 | rm *.o *.a
17 |
--------------------------------------------------------------------------------
/tests/makefile_files/lib/bar.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int bar(const char *str)
5 | {
6 | return foo(strlen(str), 3);
7 | }
8 |
--------------------------------------------------------------------------------
/tests/makefile_files/lib/foo/foo.c:
--------------------------------------------------------------------------------
1 | #include "foo.h"
2 |
3 | int foo(int len, int magic)
4 | {
5 | return len % magic;
6 | }
7 |
--------------------------------------------------------------------------------
/tests/makefile_files/lib/foo/foo.h:
--------------------------------------------------------------------------------
1 | int foo(int len, int magic);
2 |
--------------------------------------------------------------------------------
/tests/makefile_files/main.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 |
5 | int main(int argc, const char *argv[])
6 | {
7 | printf("%s: %d\n", argv[0], bar(argv[0]));
8 | return 0;
9 | }
10 |
--------------------------------------------------------------------------------
/tests/test_CppProperties.py:
--------------------------------------------------------------------------------
1 | """Test CppProperties flags generation."""
2 | import imp
3 | import platform
4 | from os import path, environ
5 | from unittest import TestCase
6 |
7 | from EasyClangComplete.plugin.flags_sources import CppProperties
8 | from EasyClangComplete.plugin.utils import tools
9 | from EasyClangComplete.plugin.utils import flag
10 | from EasyClangComplete.plugin.utils import file
11 | from EasyClangComplete.plugin.utils import search_scope
12 |
13 | imp.reload(CppProperties)
14 | imp.reload(tools)
15 | imp.reload(flag)
16 | imp.reload(file)
17 | imp.reload(search_scope)
18 |
19 | CppProperties = CppProperties.CppProperties
20 | SearchScope = search_scope.TreeSearchScope
21 | Flag = flag.Flag
22 | File = file.File
23 |
24 |
25 | def _get_test_folder(name):
26 | return path.join(path.dirname(__file__), 'CppProperties_files', name)
27 |
28 |
29 | class TestCppProperties(TestCase):
30 | """Test generating flags with a 'CppProperties.json' file."""
31 |
32 | def test_get_all_flags(self):
33 | """Test if CppProperties.json is found."""
34 | include_prefixes = ['-I']
35 | db = CppProperties(include_prefixes)
36 |
37 | expected = [
38 | Flag('-I', path.normpath('/folder/include/path')),
39 | Flag('-I', path.normpath('/another/file/path')),
40 | ]
41 |
42 | scope = SearchScope(from_folder=_get_test_folder('simple'))
43 | self.assertEqual(expected, db.get_flags(search_scope=scope))
44 |
45 | def test_expand_environment_variables(self):
46 | """Test environment variables are expanded."""
47 | include_prefixes = ['-I']
48 | db = CppProperties(include_prefixes)
49 | environ['TEST_VARIABLE_TO_EXPAND'] = '/lib_include_dir'
50 |
51 | expected = [
52 | Flag('-I', path.normpath('/lib_include_dir')),
53 | ]
54 |
55 | scope = SearchScope(from_folder=_get_test_folder('environment'))
56 | self.assertEqual(expected, db.get_flags(search_scope=scope))
57 |
58 | def test_no_db_in_folder(self):
59 | """Test if no json is found."""
60 | if platform.system() == "Darwin":
61 | # This test is disabled as the current path is trying to reach a
62 | # network resource on MacOS. I guess we have to deal with this at
63 | # some point later.
64 | return
65 | include_prefixes = ['-I']
66 | db = CppProperties(include_prefixes)
67 |
68 | expected = None
69 |
70 | self.assertEqual(expected, db.get_flags(
71 | File.canonical_path('/home/user/dummy_main.cpp')))
72 |
73 | def test_empty_include_and_defines(self):
74 | """Test that empty fields are handled correctly."""
75 | include_prefixes = ['-I']
76 | db = CppProperties(include_prefixes)
77 |
78 | expected = []
79 |
80 | scope = SearchScope(from_folder=_get_test_folder('empty'))
81 | self.assertEqual(expected, db.get_flags(search_scope=scope))
82 |
--------------------------------------------------------------------------------
/tests/test_c_cpp_properties.py:
--------------------------------------------------------------------------------
1 | """Test c_cpp_properties flags generation."""
2 | import imp
3 | import platform
4 | from os import path, environ
5 | from unittest import TestCase
6 |
7 | from EasyClangComplete.plugin.flags_sources import c_cpp_properties
8 | from EasyClangComplete.plugin.utils import tools
9 | from EasyClangComplete.plugin.utils import flag
10 | from EasyClangComplete.plugin.utils import file
11 | from EasyClangComplete.plugin.utils import search_scope
12 |
13 |
14 | imp.reload(c_cpp_properties)
15 | imp.reload(tools)
16 | imp.reload(flag)
17 | imp.reload(file)
18 | imp.reload(search_scope)
19 |
20 | CCppProperties = c_cpp_properties.CCppProperties
21 | SearchScope = search_scope.TreeSearchScope
22 | Flag = flag.Flag
23 | File = file.File
24 |
25 |
26 | class TestCCppProperties(TestCase):
27 | """Test generating flags with a 'c_cpp_properties.json' file."""
28 |
29 | def test_get_all_flags(self):
30 | """Test if c_cpp_properties.json is found."""
31 | include_prefixes = ['-I']
32 | db = CCppProperties(include_prefixes)
33 |
34 | expected = [Flag('-I', path.normpath('/lib_include_dir')),
35 | Flag('', '-Dlib_EXPORTS')]
36 | path_to_db = path.join(path.dirname(__file__),
37 | 'c_cpp_properties_files',
38 | 'simple')
39 | scope = SearchScope(from_folder=path_to_db)
40 | self.assertEqual(expected, db.get_flags(search_scope=scope))
41 |
42 | def test_expand_environment_variables(self):
43 | """Test environment variables are expanded."""
44 | include_prefixes = ['-I']
45 | db = CCppProperties(include_prefixes)
46 | environ['TEST_VARIABLE_TO_EXPAND'] = '/lib_include_dir'
47 |
48 | expected = [Flag('-I', path.normpath('/lib_include_dir')),
49 | Flag('', '-Dlib_EXPORTS')]
50 | path_to_db = path.join(path.dirname(__file__),
51 | 'c_cpp_properties_files',
52 | 'environment')
53 | scope = SearchScope(from_folder=path_to_db)
54 | print(scope)
55 | self.assertEqual(expected, db.get_flags(search_scope=scope))
56 |
57 | def test_no_db_in_folder(self):
58 | """Test if no json is found."""
59 | if platform.system() == "Darwin":
60 | # This test is disabled as the current path is trying to reach a
61 | # network resource on MacOS. I guess we have to deal with this at
62 | # some point later.
63 | return
64 | include_prefixes = ['-I']
65 | db = CCppProperties(include_prefixes)
66 |
67 | flags = db.get_flags(File.canonical_path('/home/user/dummy_main.cpp'))
68 | self.assertTrue(flags is None)
69 |
70 | def test_empty_include_and_defines(self):
71 | """Test that empty fields are handled correctly."""
72 | include_prefixes = ['-I']
73 | db = CCppProperties(include_prefixes)
74 |
75 | expected = []
76 | path_to_db = path.join(path.dirname(__file__),
77 | 'c_cpp_properties_files',
78 | 'empty')
79 | scope = SearchScope(from_folder=path_to_db)
80 | self.assertEqual(expected, db.get_flags(search_scope=scope))
81 |
--------------------------------------------------------------------------------
/tests/test_catkinizer.py:
--------------------------------------------------------------------------------
1 | """Test compilation database flags generation."""
2 | import imp
3 | import sublime
4 | import platform
5 |
6 | from os import path
7 |
8 | from EasyClangComplete.tests.gui_test_wrapper import GuiTestWrapper
9 | from EasyClangComplete.plugin.utils import catkinizer
10 | from EasyClangComplete.plugin.utils import file
11 | imp.reload(file)
12 | imp.reload(catkinizer)
13 |
14 | Catkinizer = catkinizer.Catkinizer
15 | File = file.File
16 |
17 |
18 | class BaseTestCatkinizer(object):
19 | """Test unique list."""
20 |
21 | def setUp(self):
22 | """Prepare the view and store the settings."""
23 | super(BaseTestCatkinizer, self).setUp()
24 | self.__project_data_backup = sublime.active_window().project_data()
25 | if not sublime.active_window().project_data():
26 | # Load a file and put it into current data.
27 | project_file = path.join(path.dirname(__file__),
28 | '..',
29 | 'easy_clang_complete.sublime-project')
30 | import json
31 | with open(project_file) as f:
32 | project_json = json.load(f)
33 | sublime.active_window().set_project_data(project_json)
34 |
35 | def tearDown(self):
36 | """Restore project settings and close the view."""
37 | sublime.active_window().set_project_data(self.__project_data_backup)
38 | super(BaseTestCatkinizer, self).tearDown()
39 |
40 | def test_init(self):
41 | """Test initialization."""
42 | test_file = File(
43 | path.join(path.dirname(__file__), 'cmake_tests', 'CMakeLists.txt'))
44 | catkinizer = Catkinizer(test_file)
45 | self.assertEqual(catkinizer._Catkinizer__cmake_file.full_path,
46 | test_file.full_path)
47 |
48 | def test_setting_getting_project_data(self):
49 | """Test setting and getting project data."""
50 | self.assertEqual(sublime.active_window().project_data(),
51 | Catkinizer._Catkinizer__get_sublime_project_data())
52 | Catkinizer._Catkinizer__save_sublime_project_data({})
53 | self.assertEqual(sublime.active_window().project_data(), {})
54 |
55 | def test_get_ros_distro_path(self):
56 | """Check that we can get the paths to ros.
57 |
58 | Here we just check that we get the first path from a given folder."""
59 | cmake_tests_folder = path.join(path.dirname(__file__), 'cmake_tests')
60 | print(cmake_tests_folder)
61 | picked = Catkinizer._Catkinizer__get_ros_distro_path(
62 | cmake_tests_folder + '/*')
63 | self.assertEqual(path.dirname(picked), cmake_tests_folder)
64 |
65 | def test_get_cmake_entry(self):
66 | """Get cmake entry."""
67 | project_data = Catkinizer._Catkinizer__get_sublime_project_data()
68 | settings_entry = project_data[Catkinizer._SETTINGS_TAG]
69 | flags_sources = settings_entry[Catkinizer._FLAGS_SOURCES_TAG]
70 | cmake_entry = Catkinizer._Catkinizer__get_cmake_entry(flags_sources)
71 | expected_entry = {
72 | "file": "CMakeLists.txt",
73 | "flags":
74 | [
75 | "-DCMAKE_BUILD_TYPE=Release",
76 | "-D XXXX=ON"
77 | ],
78 | "prefix_paths":
79 | [
80 | "/opt/ros/indigo",
81 | "~/Code/catkin_ws/devel",
82 | "$project_base_path/catkin_ws/devel",
83 | ]
84 | }
85 | self.assertEqual(cmake_entry, expected_entry)
86 |
87 | def test_get_catkin_ws(self):
88 | """Test getting a catkin workspace."""
89 | catkin_proj_cmake_file = File(
90 | path.join(path.dirname(__file__),
91 | 'catkin_tests',
92 | 'catkin_ws',
93 | 'src',
94 | 'project',
95 | 'CMakeLists.txt'))
96 | catkinizer = Catkinizer(catkin_proj_cmake_file)
97 | ws_path = catkinizer._Catkinizer__get_catkin_workspace_path()
98 | catkin_ws = path.join(path.dirname(__file__),
99 | 'catkin_tests', 'catkin_ws', 'devel')
100 | catkin_ws = catkin_ws.replace(path.expanduser('~'), '~', 1)
101 | self.assertEqual(ws_path, catkin_ws)
102 |
103 |
104 | print(platform.system())
105 | if platform.system() is not 'Windows':
106 | class TestCatkinizer(BaseTestCatkinizer, GuiTestWrapper):
107 | """Test class for the binary based completer."""
108 | pass
109 |
--------------------------------------------------------------------------------
/tests/test_clang_complete_file.py:
--------------------------------------------------------------------------------
1 | """Tests for cmake database generation.
2 |
3 | Attributes:
4 | FlagsFile (TYPE): Description
5 | """
6 | import imp
7 | from os import path
8 | from unittest import TestCase
9 |
10 | from EasyClangComplete.plugin.flags_sources import flags_file
11 | from EasyClangComplete.plugin.utils import flag
12 | from EasyClangComplete.plugin.utils import search_scope
13 |
14 | imp.reload(flags_file)
15 | imp.reload(flag)
16 | imp.reload(search_scope)
17 |
18 | SearchScope = search_scope.TreeSearchScope
19 |
20 | FlagsFile = flags_file.FlagsFile
21 |
22 | Flag = flag.Flag
23 |
24 |
25 | class TestFlagsFile(TestCase):
26 | """Test finding and generatgin flags from .clang_complete file.
27 |
28 | Attributes:
29 | view (TYPE): Description
30 | """
31 |
32 | def test_init(self):
33 | """Initialization test."""
34 | self.assertEqual(FlagsFile._FILE_NAME, '.clang_complete')
35 |
36 | def test_load_file(self):
37 | """Test finding and loading existing file."""
38 | test_file_path = path.join(
39 | path.dirname(__file__), 'test_files', 'test.cpp')
40 |
41 | flags_file = FlagsFile(['-I', '-isystem'])
42 | flags = flags_file.get_flags(test_file_path)
43 | # This flag only exists in .clang_complete to help us test that
44 | # we can read the flag.
45 | self.assertIn(Flag('', '-Wabi'), flags)
46 |
47 | def test_fail_to_find(self):
48 | """Test failing to find a .clang_complete file."""
49 | test_file_path = path.join(
50 | path.dirname(__file__), 'test_files', 'test.cpp')
51 |
52 | folder = path.dirname(test_file_path)
53 | flags_file = FlagsFile(['-I', '-isystem'])
54 | wrong_scope = SearchScope(from_folder=folder, to_folder=folder)
55 | flags = flags_file.get_flags(test_file_path, wrong_scope)
56 | self.assertIs(flags, None)
57 |
--------------------------------------------------------------------------------
/tests/test_clang_utils.py:
--------------------------------------------------------------------------------
1 | """Test clang utilities."""
2 | import imp
3 | from unittest import TestCase
4 |
5 | from EasyClangComplete.plugin.utils import clang_utils
6 |
7 | imp.reload(clang_utils)
8 |
9 | ClangUtils = clang_utils.ClangUtils
10 |
11 |
12 | class test_clang_utils(TestCase):
13 | """Test other things."""
14 |
15 | def test_get_cindex(self):
16 | """Test that we get a correct clang module."""
17 | module = ClangUtils.get_cindex_module_for_version("3.8")
18 | self.assertTrue(module.endswith('cindex38'))
19 | module = ClangUtils.get_cindex_module_for_version("9.0")
20 | self.assertTrue(module.endswith('cindex50'))
21 | # Check that we return the latest cindex for unsupported ones.
22 | module = ClangUtils.get_cindex_module_for_version("999.0")
23 | self.assertTrue(module.endswith('cindex50'))
24 |
25 | def test_get_apple_version(self):
26 | """Test that we get a correct clang module."""
27 | apple_version_output = 'Apple LLVM version 10.0.1'
28 | version = ClangUtils._get_apple_clang_version_str(apple_version_output)
29 | self.assertEquals(version, '6.0')
30 | # Check that we are pretty future proof.
31 | apple_version_output = 'Apple LLVM version 99.0.1'
32 | version = ClangUtils._get_apple_clang_version_str(apple_version_output)
33 | self.assertEquals(version, '7.0')
34 |
35 | def test_get_all_possible_filenames(self):
36 | """Test that we get a correct clang module."""
37 | all_paths = ClangUtils.get_all_possible_filenames('3.8')
38 | self.assertGreater(len(all_paths), 0)
39 | for path in all_paths:
40 | self.assertNotIn('$version', path)
41 |
42 | def test_find_libclang(self):
43 | """Test that we get a correct clang module."""
44 | version_str = ClangUtils.get_clang_version_str('clang++')
45 | libclang_dir, full_libclang_path = ClangUtils.find_libclang(
46 | 'clang++', 'blah', version_str)
47 | self.assertIsNotNone(libclang_dir)
48 | self.assertIsNotNone(full_libclang_path)
49 | from os import path
50 | self.assertEquals(path.dirname(full_libclang_path), libclang_dir)
51 |
--------------------------------------------------------------------------------
/tests/test_docs.py:
--------------------------------------------------------------------------------
1 | """Test that all docs are there."""
2 | from os import path
3 | from unittest import TestCase
4 |
5 |
6 | def parse_code_headers(md_file_path):
7 | """Parse all settings names from the markdown."""
8 | import re
9 | all_settings_headers_regex = re.compile(r"###\s\*\*`(\w+)`\*\*.*")
10 | with open(md_file_path) as f:
11 | contents = f.read()
12 | matches = all_settings_headers_regex.findall(contents)
13 | return matches
14 |
15 |
16 | def parse_settings(json_file_path):
17 | """Parse all settings names from the json file."""
18 | import re
19 | all_settings_regex = re.compile(r'^ "(\w+)"\s*:.+$', flags=re.MULTILINE)
20 | with open(json_file_path) as f:
21 | contents = f.read()
22 | matches = all_settings_regex.findall(contents)
23 | return matches
24 |
25 |
26 | class TestSomething(TestCase):
27 | """Test that the settings have descriptions in the docs."""
28 |
29 | def test_all_settings(self):
30 | """Test that all settings have docs."""
31 | project_folder = path.dirname(path.dirname(__file__))
32 | md_file = path.join(project_folder, 'docs', 'settings.md')
33 | settings_file = path.join(
34 | project_folder, 'EasyClangComplete.sublime-settings')
35 | self.assertEqual(set(parse_code_headers(md_file)),
36 | set(parse_settings(settings_file)))
37 |
--------------------------------------------------------------------------------
/tests/test_files/Makefile.cmake:
--------------------------------------------------------------------------------
1 | # CMAKE generated file: DO NOT EDIT!
2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.5
3 |
4 | # The generator used is:
5 | set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles")
6 |
7 | # The top level Makefile was generated from the following files:
8 | set(CMAKE_MAKEFILE_DEPENDS
9 | "CMakeCache.txt"
10 | "/usr/share/cmake-3.5/Modules/CMakeCCompiler.cmake.in"
11 | "/usr/share/cmake-3.5/Modules/Platform/UnixPaths.cmake"
12 | )
13 |
14 | # The corresponding makefile is:
15 | set(CMAKE_MAKEFILE_OUTPUTS
16 | "Makefile"
17 | "CMakeFiles/cmake.check_cache"
18 | )
19 |
20 | # Byproducts of CMake generate step:
21 | set(CMAKE_MAKEFILE_PRODUCTS
22 | "CMakeFiles/3.5.1/CMakeSystem.cmake"
23 | "lib/CMakeFiles/CMakeDirectoryInformation.cmake"
24 | )
25 |
26 | # Dependency information for all targets:
27 | set(CMAKE_DEPEND_INFO_FILES
28 | "CMakeFiles/test_a.dir/DependInfo.cmake"
29 | "lib/CMakeFiles/liba.dir/DependInfo.cmake"
30 | )
31 |
--------------------------------------------------------------------------------
/tests/test_files/test.cpp:
--------------------------------------------------------------------------------
1 | class A {
2 | int a;
3 | void foo(int a);
4 | public:
5 | void foo(double a);
6 | };
7 | int main(int argc, char const *argv[]) {
8 | A a;
9 | a.
10 | return 0;
11 | }
12 |
--------------------------------------------------------------------------------
/tests/test_files/testTemplatesManual.cpp:
--------------------------------------------------------------------------------
1 | /// File using several C++ libraries with templated types,
2 | /// useful for manual testing of popup info by hovering over code.
3 | /// Not added to auto-testing because popups include
4 | /// libC++ implementation details that can change without warning,
5 | /// making it difficult to test for correct info in the popups.
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | class A {
13 | int a;
14 | void foo(int a);
15 | public:
16 | void foo(double a);
17 |
18 | template
19 | int bar() { return BarTemplateParameter;}
20 |
21 | template
22 | void barTemp3();
23 |
24 | template
25 | int barM(std::shared_ptr a, const std::shared_ptr& aConst) { return M;}
26 |
27 | std::shared_ptr& barNoTempl(
28 | std::shared_ptr sharedPtr,
29 | const std::shared_ptr& constRefToSharedPtr,
30 | std::shared_ptr&& rValueRefToSharedPtr);
31 | };
32 |
33 |
34 | template
35 | class Templated {
36 | };
37 |
38 | template
39 | class TemplatedTwo {
40 | };
41 |
42 | int main(int argc, char const *argv[]) {
43 | std::shared_ptr pointerToA;
44 | pointerToA.reset();
45 | pointerToA->bar<5>();
46 | pointerToA->barTemp3();
47 | pointerToA->barM<5>(pointerToA, pointerToA);
48 | pointerToA.reset(pointerToA.get());
49 | std::pair, std::string> myPair;
50 | myPair.first = nullptr;
51 |
52 | A justA;
53 | A& refA = justA;
54 | A* ptrA;
55 | A*& ptrRefA = ptrA;
56 | A&& rvalueRefA = std::move(justA);
57 | Templated templatedInt;
58 | Templated templatedA;
59 | Templated templatedOnARvalueRef;
60 | Templated*>* templatedSharedPtrARvalueRef;
61 | Templated&& templatedARValueRef = std::move(templatedA);
62 | Templated templatedAPtr;
63 | Templated& templatedAPtrRef = templatedAPtr;
64 | Templated> templatedSharedPtrAPtr;
65 | Templated> templatedConstSharedPtrAPtr;
66 | Templated*>* templatedConstSharedPtrAPtrPtr;
67 | Templated> templatedSharedPtrA;
68 | Templated> templatedSharedPtrConstA;
69 | Templated> templatedConstSharedPtrConstA;
70 |
71 | TemplatedTwo templatedTwoAA;
72 | TemplatedTwo, const std::shared_ptr*> templatedTwoSharedConstA_ConstSharedPtrPointer;
73 | A a;
74 | a.foo(2.0);
75 |
76 | std::array arraySize5;
77 |
78 | auto lambda = [](std::shared_ptr a) {
79 | return a;
80 | };
81 | lambda(pointerToA);
82 | return 0;
83 | }
84 |
--------------------------------------------------------------------------------
/tests/test_files/test_changes.cpp:
--------------------------------------------------------------------------------
1 | int main(int argc, char const *argv[]) {
2 | /* code */
3 | return 0;
4 | }
5 |
--------------------------------------------------------------------------------
/tests/test_files/test_errors.cpp:
--------------------------------------------------------------------------------
1 | int main(int argc, char const *argv[]) {
2 | foo.
3 | return 0;
4 | }
5 |
--------------------------------------------------------------------------------
/tests/test_files/test_info.cpp:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | /// @brief Class for my cool class.
3 | ///
4 | class MyCoolClass {
5 | public:
6 | /**
7 | * @brief This is short.
8 | *
9 | * And this is a full comment.
10 | *
11 | * @param[in] a param a
12 | * @param[in] b param b
13 | */
14 | void foo(int a, int b);
15 | };
16 |
17 | int main(int argc, char const *argv[]) {
18 | MyCoolClass cool_class;
19 | cool_class.foo(2, 2);
20 | return 0;
21 | }
22 |
--------------------------------------------------------------------------------
/tests/test_files/test_info_arguments_link.cpp:
--------------------------------------------------------------------------------
1 | class Foo {};
2 |
3 | class MyCoolClass {
4 | public:
5 | void foo(Foo a, Foo* b);
6 | };
7 |
8 | int main(int argc, char const *argv[]) {
9 | MyCoolClass cool_class;
10 | cool_class.foo(Foo(), nullptr);
11 | return 0;
12 | }
13 |
--------------------------------------------------------------------------------
/tests/test_files/test_location.cpp:
--------------------------------------------------------------------------------
1 | class MyCoolClass {
2 | public:
3 | void foo() {
4 | // Do nothing.
5 | }
6 | };
7 |
8 | int main(int argc, char const *argv[]) {
9 | MyCoolClass cool_class;
10 | cool_class.foo();
11 | return 0;
12 | }
13 |
--------------------------------------------------------------------------------
/tests/test_files/test_method_one_parameter.m:
--------------------------------------------------------------------------------
1 | #include
2 | @interface Foo : NSObject
3 | -(void) oneParameterMethod:(BOOL)boolParam;
4 | @end
5 | int main(int argc, char const *argv[]) {
6 | Foo* foo = [[Foo alloc] init];
7 | [foo
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/tests/test_files/test_method_two_parameters.m:
--------------------------------------------------------------------------------
1 | #include
2 | @interface Foo : NSObject
3 | -(NSInteger*) bar:(BOOL)b1 strParam:(NSString*)str1;
4 | @end
5 | int main(int argc, char const *argv[]) {
6 | Foo* foo = [[Foo alloc] init];
7 | [foo
8 | }
9 |
--------------------------------------------------------------------------------
/tests/test_files/test_objective_c.m:
--------------------------------------------------------------------------------
1 | // A bunch of different types of protocols/methods
2 |
3 | #import
4 | #import
5 |
6 | @class Foo;
7 |
8 | @protocol Protocol
9 | -(void)protocolMethodVoidNoParameters; ///< Has a brief comment
10 | -(BOOL)protocolMethodBoolNoParameters;
11 | -(void)protocolMethodVoidOneStringParameter:(NSString*)s1;
12 | -(void)protocolMethodVoidTwoStringParameters:(NSString*)s1
13 | stringParam2:(NSString*)s2;
14 | +(void)protocolClassMethod;
15 | @property (assign) BOOL protocolPropertyBool;
16 | @end
17 |
18 | @interface Interface : NSObject
19 | -(void)interfaceMethodVoidNoParameters; ///< Brief comment.
20 | -(BOOL)interfaceMethodBoolNoParameters;
21 | -(void)interfaceMethodVoidOneStringParameter:(NSString*)s1;
22 | -(void)interfaceMethodVoidTwoStringParameters:(NSString*)s1
23 | stringParam2:(NSString*)s2;
24 | -(void)interfaceMethodVoidTwoParametersSecondUnnamed:(int)int1
25 | :(int)int2;
26 | +(Foo*)interfaceClassMethodFooTwoFooParameters:(Foo*)f1
27 | fooParam2:(Foo*)f2;
28 | @property (assign) NSString* interfacePropertyString;
29 | @end
30 |
31 | @implementation Interface
32 | @synthesize protocolPropertyBool;
33 |
34 | -(void)interfaceMethodVoidNoParameters {}
35 | -(BOOL)interfaceMethodBoolNoParameters { return YES; }
36 | -(void)interfaceMethodVoidOneStringParameter:(NSString*)s1 {}
37 | -(void)interfaceMethodVoidTwoStringParameters:(NSString*)s1
38 | stringParam2:(NSString*)s2 {}
39 | -(void)interfaceMethodVoidTwoParametersSecondUnnamed:(int)int1
40 | :(int)int2 {}
41 | +(Foo*)interfaceClassMethodFooTwoFooParameters:(Foo*)f1
42 | fooParam2:(Foo*)f2 { return nil; }
43 |
44 | -(void)protocolMethodVoidNoParameters {}
45 | -(BOOL)protocolMethodBoolNoParameters { return YES; }
46 | -(void)protocolMethodVoidOneStringParameter:(NSString*)s1 {}
47 | -(void)protocolMethodVoidTwoStringParameters:(NSString*)s1
48 | stringParam2:(NSString*)s2 {}
49 | +(void)protocolClassMethod {}
50 |
51 | @end
52 |
53 | @interface Interface (Category)
54 | -(void)categoryMethodVoidNoParameters;
55 | @end
56 |
57 | @implementation Interface (Category)
58 | -(void)categoryMethodVoidNoParameters{}
59 | @end
60 |
61 | /// Just a bunch of calls used to help manually test tooltip popups
62 | int main(int argc, const char * argv[])
63 | {
64 | Interface* interface = [[Interface alloc] init];
65 |
66 | [interface interfaceMethodVoidNoParameters];
67 | [interface interfaceMethodBoolNoParameters];
68 | [interface interfaceMethodVoidOneStringParameter:nil];
69 | [interface interfaceMethodVoidTwoStringParameters:nil stringParam2:nil];
70 | [interface interfaceMethodVoidTwoParametersSecondUnnamed:0 :0];
71 | [Interface interfaceClassMethodFooTwoFooParameters:nil fooParam2:nil];
72 | interface.interfacePropertyString = nil;
73 |
74 | [interface protocolMethodVoidNoParameters];
75 | [interface protocolMethodBoolNoParameters];
76 | [interface protocolMethodVoidOneStringParameter:nil];
77 | [interface protocolMethodVoidTwoStringParameters:nil stringParam2:nil];
78 | [Interface protocolClassMethod];
79 | interface.protocolPropertyBool = YES;
80 |
81 | [interface categoryMethodVoidNoParameters];
82 |
83 | [interface performSelector:@selector(interfaceMethodVoidNoParameters)];
84 |
85 | id protocol = nil;
86 | [protocol protocolMethodVoidNoParameters];
87 | [protocol protocolMethodBoolNoParameters];
88 | [protocol protocolMethodVoidOneStringParameter:nil];
89 | [protocol protocolMethodVoidTwoStringParameters:nil stringParam2:nil];
90 |
91 | interface.
92 | NSLog(@"Hello world");
93 |
94 | return 0;
95 | }
96 |
97 |
--------------------------------------------------------------------------------
/tests/test_files/test_objective_c_covariant.m:
--------------------------------------------------------------------------------
1 | #import
2 | @class Foo;
3 | @interface MyCovariant<__covariant ObjectType> : NSObject
4 | -(MyCovariant*)covariantMethod;
5 | @end
6 |
--------------------------------------------------------------------------------
/tests/test_files/test_objective_cpp.mm:
--------------------------------------------------------------------------------
1 | #include
2 | int main(int argc, char const *argv[]) {
3 | std::string str;
4 | str.
5 | }
6 |
--------------------------------------------------------------------------------
/tests/test_files/test_property.m:
--------------------------------------------------------------------------------
1 | #include
2 | @interface Foo : NSObject
3 | @property BOOL boolProperty;
4 | @end
5 | int main(int argc, char const *argv[]) {
6 | Foo* foo = [[Foo alloc] init];
7 | foo.
8 | }
9 |
--------------------------------------------------------------------------------
/tests/test_files/test_templates.cpp:
--------------------------------------------------------------------------------
1 | class Foo;
2 | template
3 | class TemplateClass
4 | {
5 | public:
6 | void foo(TemplateClass);
7 | };
8 | int main(int argc, char const *argv[]) {
9 | TemplateClass instanceClassTypeInt;
10 | TemplateClass instanceClassAndDefaults;
11 | TemplateClass> instanceNested;
12 | TemplateClass instancePointer;
13 | TemplateClass instanceRef;
14 | TemplateClass instanceRValueRef;
15 | instanceRValueRef.foo(instanceRValueRef);
16 | return 0;
17 | }
18 |
--------------------------------------------------------------------------------
/tests/test_files/test_unicode.cpp:
--------------------------------------------------------------------------------
1 | // This file has some unicode characters in the comments
2 | // that should not disrupt ECC
3 | // ` ©
4 | class Foo {};
5 | int main(int argc, char const *argv[]) {
6 | Foo foo;
7 | }
8 |
--------------------------------------------------------------------------------
/tests/test_files/test_vector.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | int main(int argc, char const *argv[]) {
3 | std::vector vec;
4 | vec.
5 | }
6 |
--------------------------------------------------------------------------------
/tests/test_files/test_void_method.m:
--------------------------------------------------------------------------------
1 | #include
2 | @interface Foo : NSObject
3 | -(void) voidMethod;
4 | @end
5 | int main(int argc, char const *argv[]) {
6 | Foo* foo = [[Foo alloc] init];
7 | [foo
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/tests/test_files/test_wrong_triggers.cpp:
--------------------------------------------------------------------------------
1 | int main(int argc, char const *argv[]) {
2 | int a = 2;
3 | a > 2.
4 | }
--------------------------------------------------------------------------------
/tests/test_flag.py:
--------------------------------------------------------------------------------
1 | """Tests for flag class."""
2 | import imp
3 | from unittest import TestCase
4 |
5 | from EasyClangComplete.plugin.utils import flag
6 |
7 | imp.reload(flag)
8 |
9 | Flag = flag.Flag
10 |
11 |
12 | class TestFlag(TestCase):
13 | """Test getting flags from CMakeLists.txt."""
14 |
15 | def test_init(self):
16 | """Initialization test."""
17 | flag = Flag.Builder().from_unparsed_string("-Ihello").build()
18 | self.assertEqual(flag.as_list(), ["-I", "hello"])
19 | self.assertEqual(flag.prefix, "-I")
20 | self.assertEqual(flag.body, "hello")
21 | self.assertEqual(str(flag), "-Ihello")
22 | flag = Flag("hello", "world", " ")
23 | self.assertEqual(flag.as_list(), ["hello", "world"])
24 | self.assertEqual(flag.prefix, "hello")
25 | self.assertEqual(flag.body, "world")
26 | self.assertEqual(flag.separator, " ")
27 | self.assertEqual(str(flag), "hello world")
28 |
29 | def test_hash(self):
30 | """Test that hash is always the same when needed."""
31 | flag1 = Flag("hello", "world")
32 | flag2 = Flag("hello", "world")
33 | flag3 = Flag("world", "hello")
34 | self.assertEqual(hash(flag1), hash(flag2))
35 | self.assertNotEqual(hash(flag1), hash(flag3))
36 |
37 | def test_put_into_container(self):
38 | """Test adding to hashed container."""
39 | flags_set = set()
40 | flag1 = Flag("", "hello")
41 | flag2 = Flag("", "world")
42 | flag3 = Flag("hello", "world")
43 | flag4 = Flag("world", "hello")
44 | flags_set.add(flag1)
45 | flags_set.add(flag2)
46 | flags_set.add(flag3)
47 | self.assertIn(flag1, flags_set)
48 | self.assertIn(flag2, flags_set)
49 | self.assertIn(flag3, flags_set)
50 | self.assertNotIn(flag4, flags_set)
51 |
52 | def test_tokenize(self):
53 | """Test tokenizing a list of all split flags."""
54 | split_str = ["-I", "hello", "-Iblah", "-isystem", "world"]
55 | list_of_flags = Flag.tokenize_list(split_str)
56 | self.assertTrue(len(list_of_flags), 3)
57 | self.assertIn(Flag("-I", "hello", " "), list_of_flags)
58 | self.assertIn(Flag("-I", "blah"), list_of_flags)
59 | self.assertIn(Flag("-isystem", "world", " "), list_of_flags)
60 |
61 | def test_builder(self):
62 | """Test tokenizing a list of all split flags."""
63 | flag1 = Flag.Builder().with_prefix('hello').with_body('world').build()
64 | self.assertEqual(Flag("hello", "world"), flag1)
65 | flag3 = Flag.Builder().from_unparsed_string('-Iworld').build()
66 | self.assertEqual(Flag("-I", "world"), flag3)
67 | flag4 = Flag.Builder().from_unparsed_string('-include world').build()
68 | self.assertEqual(Flag("-include", "world", " "), flag4)
69 | # Check that we don't trigger on /U flag.
70 | import platform
71 | if platform.system() != "Windows":
72 | flag5 = Flag.Builder().from_unparsed_string('/User/blah').build()
73 | self.assertEqual(Flag("", "", ""), flag5)
74 |
75 | def test_builder_invalid(self):
76 | """Test tokenizing invalid flags."""
77 | flag2 = Flag.Builder().from_unparsed_string('hello world').build()
78 | self.assertEqual(Flag("", ""), flag2)
79 |
--------------------------------------------------------------------------------
/tests/test_flags_source.py:
--------------------------------------------------------------------------------
1 | """Tests for cmake database generation."""
2 | import imp
3 | from os import path
4 | from unittest import TestCase
5 |
6 | from EasyClangComplete.plugin.flags_sources import flags_source
7 | from EasyClangComplete.plugin.utils import flag
8 |
9 | imp.reload(flags_source)
10 | imp.reload(flag)
11 |
12 | FlagsSource = flags_source.FlagsSource
13 | Flag = flag.Flag
14 |
15 |
16 | class TestFlagsSource(TestCase):
17 | """Test getting flags from a list of chunks."""
18 |
19 | def test_init(self):
20 | """Initialization test."""
21 | include_prefixes = ["-I", "-isystem"]
22 | flags_source = FlagsSource(include_prefixes)
23 | self.assertEqual(flags_source._include_prefixes, include_prefixes)
24 |
25 | def test_parse_flags(self):
26 | """Test that the flags are parsed correctly."""
27 | from os import listdir
28 | current_folder = path.dirname(__file__)
29 | folder_to_expand = path.join(current_folder, '*')
30 | initial_str_flags = ["-I", current_folder, "-I" + current_folder,
31 | "-isystem", current_folder, "-std=c++11",
32 | "#simulate a comment",
33 | "-Iblah\n", "-I", "blah", "-I" + folder_to_expand]
34 | flags = Flag.tokenize_list(initial_str_flags, current_folder)
35 | expected_blah_path = path.join(current_folder, "blah")
36 | self.assertIn(Flag("-I", current_folder, " "), flags)
37 | self.assertIn(Flag("-I", current_folder), flags)
38 | self.assertIn(Flag("-isystem", current_folder, " "), flags)
39 | self.assertIn(Flag("-I", expected_blah_path, " "), flags)
40 | self.assertIn(Flag("-I", expected_blah_path), flags)
41 | self.assertIn(Flag("", "-std=c++11"), flags)
42 |
43 | # Check star expansion for a flags source
44 | for child in listdir(current_folder):
45 | child = path.join(current_folder, child)
46 | if path.isdir(child):
47 | self.assertIn(Flag("-I", child), flags)
48 |
49 | self.assertNotIn(Flag("", "-Iblah"), flags)
50 | self.assertNotIn(Flag("-I", "blah", " "), flags)
51 | self.assertNotIn(Flag("", "-isystem" + current_folder), flags)
52 |
--------------------------------------------------------------------------------
/tests/test_index_location.py:
--------------------------------------------------------------------------------
1 | """Test index location."""
2 | import imp
3 | from unittest import TestCase
4 |
5 | from EasyClangComplete.plugin.utils import index_location
6 |
7 | imp.reload(index_location)
8 |
9 | IndexLocation = index_location.IndexLocation
10 |
11 |
12 | class test_index_location(TestCase):
13 | """Test generating an index location."""
14 |
15 | def test_simple_init(self):
16 | """Test short initialization."""
17 | location = IndexLocation(filename='test.cpp', line=10, column=10)
18 | self.assertEqual(location.file.name, 'test.cpp')
19 | self.assertEqual(location.file.extension, '.cpp')
20 | self.assertEqual(location.file.short_name, 'test.cpp')
21 | self.assertEqual(location.line, 10)
22 | self.assertEqual(location.column, 10)
23 |
24 | def test_full_init(self):
25 | """Test full initialization."""
26 | from os import path
27 | long_path = path.join('some', 'folder', 'test.cpp')
28 | location = IndexLocation(filename=long_path, line=10, column=10)
29 | self.assertEqual(location.file.name, long_path)
30 | self.assertEqual(location.file.extension, '.cpp')
31 | self.assertEqual(location.file.short_name, 'test.cpp')
32 |
33 | def test_no_extension(self):
34 | """Test if we can initialize without the extension."""
35 | from os import path
36 | long_path = path.join('some', 'folder', 'test')
37 | location = IndexLocation(filename=long_path, line=10, column=10)
38 | self.assertEqual(location.file.name, long_path)
39 | self.assertEqual(location.file.extension, '')
40 | self.assertEqual(location.file.short_name, 'test')
41 |
--------------------------------------------------------------------------------
/tests/test_macro_parser.py:
--------------------------------------------------------------------------------
1 | """Test macro parsing."""
2 | from unittest import TestCase
3 |
4 | from EasyClangComplete.plugin.utils.macro_parser import MacroParser
5 |
6 |
7 | class TestMacroParser(TestCase):
8 | """Tests MacroParser."""
9 |
10 | def test_args_string_non_function_like_macro(self):
11 | """Test parsing a macro with no '()'."""
12 | parser = MacroParser('TEST_MACRO', None)
13 | parser._parse_macro_file_lines(
14 | macro_file_lines=['#define TEST_MACRO 1'],
15 | macro_line_number=1)
16 | self.assertEqual(parser.args_string, '')
17 |
18 | def test_args_string_function_macro_no_args(self):
19 | """Test parsing a function-like macro that takes no arguments."""
20 | parser = MacroParser('TEST_MACRO', None)
21 | parser._parse_macro_file_lines(
22 | macro_file_lines=['#define TEST_MACRO() 1'],
23 | macro_line_number=1)
24 | self.assertEqual(parser.args_string, '()')
25 |
26 | def test_args_string_function_macro_one_arg(self):
27 | """Test parsing a function-like macro that takes one argument."""
28 | parser = MacroParser('TEST_MACRO', None)
29 | parser._parse_macro_file_lines(
30 | macro_file_lines=['#define TEST_MACRO(x) (x)'],
31 | macro_line_number=1)
32 | self.assertEqual(parser.args_string, '(x)')
33 |
34 | def test_args_string_function_macro_multiple_args(self):
35 | """Test parsing a function-like macro that takes multiple arguments."""
36 | parser = MacroParser('TEST_MACRO', None)
37 | parser._parse_macro_file_lines(
38 | macro_file_lines=['#define TEST_MACRO(x, y, z) (x + y + z)'],
39 | macro_line_number=1)
40 | self.assertEqual(parser.args_string, '(x, y, z)')
41 |
42 | def test_args_string_macro_extra_whitespace(self):
43 | """Test parsing a function-like macro with extra whitespace."""
44 | parser = MacroParser('TEST_MACRO', None)
45 | parser._parse_macro_file_lines(
46 | macro_file_lines=[' # define TEST_MACRO( x , y, z ) (x)'],
47 | macro_line_number=1)
48 | self.assertEqual(parser.args_string, '(x, y, z)')
49 |
50 | def test_body_string_macro_empty(self):
51 | """Test parsing a macro without parameters."""
52 | parser = MacroParser('TEST_MACRO', None)
53 | parser._parse_macro_file_lines(
54 | macro_file_lines=[' # define TEST_MACRO'],
55 | macro_line_number=1)
56 | self.assertEqual(parser.body_string, '')
57 |
58 | def test_body_string_macro_inline(self):
59 | """Test parsing a single-line macro."""
60 | parser = MacroParser('TEST_MACRO', None)
61 | parser._parse_macro_file_lines(
62 | macro_file_lines=[' # define TEST_MACRO 42'],
63 | macro_line_number=1)
64 | self.assertEqual(parser.body_string, '42')
65 |
66 | def test_body_string_macro_next_line(self):
67 | """Test parsing a macro with val on next line."""
68 | parser = MacroParser('TEST_MACRO', None)
69 | parser._parse_macro_file_lines(
70 | macro_file_lines=[' # define TEST_MACRO \\\n 42'],
71 | macro_line_number=1)
72 | self.assertEqual(parser.body_string, '\\\n 42')
73 |
74 | def test_body_string_macro_curr_next_line(self):
75 | """Test parsing a macro with val on current and next lines."""
76 | parser = MacroParser('TEST_MACRO', None)
77 | parser._parse_macro_file_lines(
78 | macro_file_lines=[' # define TEST_MACRO 24\\\n 42'],
79 | macro_line_number=1)
80 | self.assertEqual(parser.body_string, '24\\\n 42')
81 |
82 | def test_body_string_macro_curr_next_lines(self):
83 | """Test parsing a function macro on multiple lines."""
84 | parser = MacroParser('TEST_MACRO', None)
85 | parser._parse_macro_file_lines(
86 | macro_file_lines=[' #define TEST_MACRO(x) 24\\\n 42\\\n11\\\n123'],
87 | macro_line_number=1)
88 | self.assertEqual(parser.body_string, '24\\\n 42\\\n11\\\n123')
89 |
--------------------------------------------------------------------------------
/tests/test_makefile.py:
--------------------------------------------------------------------------------
1 | """Tests for Makefile flags extraction."""
2 | import imp
3 | import platform
4 | from os import path
5 | from unittest import TestCase
6 |
7 | from EasyClangComplete.plugin.utils import flag
8 | from EasyClangComplete.plugin.utils import search_scope
9 | from EasyClangComplete.plugin.flags_sources import makefile
10 |
11 | imp.reload(makefile)
12 | imp.reload(flag)
13 | imp.reload(search_scope)
14 |
15 | SearchScope = search_scope.TreeSearchScope
16 |
17 | Makefile = makefile.Makefile
18 |
19 | Flag = flag.Flag
20 |
21 |
22 | class TestMakefile(object):
23 | """Test finding and generating flags from Makeifles."""
24 |
25 | def test_init(self):
26 | """Initialization test."""
27 | self.assertEqual(Makefile._FILE_NAME, 'Makefile')
28 |
29 | def _get_project_root(self):
30 | return path.join(path.dirname(__file__), 'makefile_files')
31 |
32 | def _check_include(self, flags, include):
33 | expected = path.join(self._get_project_root(), include)
34 | self.assertIn(Flag('-I', expected), flags)
35 |
36 | def _check_define(self, flags, define):
37 | self.assertIn(Flag('', '-D' + define), flags)
38 |
39 | def _check_makefile(self, cache, flags, test_path, makefile_path):
40 | expected = path.join(self._get_project_root(), makefile_path)
41 | self.assertEqual(expected, cache[test_path])
42 | self.assertEqual(flags, cache[expected])
43 |
44 | def _check_cache(self, cache, flags, makefile_path):
45 | key = path.join(self._get_project_root(), makefile_path)
46 | self.assertEqual(flags, cache[key])
47 |
48 | def test_makefile_root(self):
49 | """Test finding and parsing root Makefile."""
50 | test_path = path.join(self._get_project_root(), 'main.c')
51 |
52 | mfile = Makefile(['-I', '-isystem'])
53 | flags = mfile.get_flags(test_path)
54 | self._check_include(flags, "inc")
55 | self._check_define(flags, "REQUIRED_DEFINE")
56 | self._check_makefile(mfile._cache, flags, test_path, "Makefile")
57 |
58 | def test_makefile_lib(self):
59 | """Test finding and parsing library Makefile."""
60 | test_path = path.join(self._get_project_root(), 'lib', 'bar.c')
61 |
62 | mfile = Makefile(['-I', '-isystem'])
63 | flags = mfile.get_flags(test_path)
64 | self._check_include(flags, path.join("lib", "foo"))
65 | self._check_makefile(mfile._cache, flags, test_path,
66 | path.join("lib", "Makefile"))
67 |
68 | def test_makefile_sub(self):
69 | """Test finding and parsing Makefile for library subdir."""
70 | test_path = path.join(self._get_project_root(), 'lib', 'foo', 'foo.c')
71 |
72 | mfile = Makefile(['-I', '-isystem'])
73 | flags = mfile.get_flags(test_path)
74 | self._check_include(flags, path.join("lib", "foo"))
75 | self._check_makefile(mfile._cache, flags, test_path,
76 | path.join("lib", "Makefile"))
77 |
78 | def test_makefile_fail(self):
79 | """Test behavior when no Makefile found."""
80 | test_path = path.join(path.dirname(__file__), 'test_files', 'test.cpp')
81 |
82 | mfile = Makefile(['-I', '-isystem'])
83 | flags = mfile.get_flags(test_path)
84 | self.assertTrue(flags is None)
85 |
86 |
87 | if platform.system() != "Windows":
88 | class MakefileTestRunner(TestMakefile, TestCase):
89 | """Run make only if we are not on windows."""
90 | pass
91 |
--------------------------------------------------------------------------------
/tests/test_output_panel_handler.py:
--------------------------------------------------------------------------------
1 | """Test OutputPanelHandler."""
2 |
3 | from EasyClangComplete.plugin.utils import output_panel_handler
4 | from unittest import TestCase
5 |
6 | import time
7 | import imp
8 | import sublime
9 |
10 | imp.reload(output_panel_handler)
11 |
12 | OutputPanelHandler = output_panel_handler.OutputPanelHandler
13 |
14 |
15 | class TestOutputPanelHandler(TestCase):
16 | """Test that we can create an output panel."""
17 |
18 | def tearDown(self):
19 | """Cleanup method run after every test."""
20 | window = sublime.active_window()
21 | window.run_command("show_panel", {"panel": "output.UnitTesting"})
22 |
23 | def test_panel_creation(self):
24 | """Test that we can open a panel."""
25 | OutputPanelHandler.show("hello world")
26 | window = sublime.active_window()
27 | self.assertIsNotNone(window.active_panel())
28 | self.assertEqual(window.active_panel(), OutputPanelHandler.PANEL_NAME)
29 | panel_view = window.find_output_panel(OutputPanelHandler.PANEL_TAG)
30 | contents = panel_view.substr(sublime.Region(0, panel_view.size()))
31 | self.assertEqual(contents, "hello world")
32 |
33 | def test_panel_closing(self):
34 | """Test that we can close a panel."""
35 | OutputPanelHandler.show("hello world")
36 | window = sublime.active_window()
37 | self.assertEqual(window.active_panel(), OutputPanelHandler.PANEL_NAME)
38 | OutputPanelHandler.hide_panel()
39 | self.assertIsNone(window.active_panel())
40 |
41 | def test_not_closing_panel(self):
42 | """Test that we don't close a panel with a wrong name."""
43 | window = sublime.active_window()
44 | test_panel_name = "test_panel"
45 | panel_view = window.create_output_panel(test_panel_name)
46 | while panel_view.is_loading():
47 | time.sleep(0.1)
48 | if not window.active_panel():
49 | # We cannot initialize a panel probably because of a CI quirk.
50 | return
51 | self.assertIsNotNone(window.active_panel())
52 | self.assertNotEqual(window.active_panel(),
53 | OutputPanelHandler.PANEL_NAME)
54 | OutputPanelHandler.hide_panel()
55 | self.assertIsNotNone(window.active_panel())
56 | self.assertNotEqual(window.active_panel(),
57 | OutputPanelHandler.PANEL_NAME)
58 | window.destroy_output_panel(test_panel_name)
59 |
--------------------------------------------------------------------------------
/tests/test_panel_handler.py:
--------------------------------------------------------------------------------
1 | """Test compilation database flags generation."""
2 | import imp
3 |
4 | from EasyClangComplete.tests.gui_test_wrapper import GuiTestWrapper
5 | from EasyClangComplete.plugin.utils import quick_panel_handler
6 | imp.reload(quick_panel_handler)
7 |
8 | ErrorQuickPanelHandler = quick_panel_handler.ErrorQuickPanelHandler
9 |
10 |
11 | class test_panel_handler(GuiTestWrapper):
12 | """Test unique list."""
13 |
14 | def test_init(self):
15 | """Test initialization."""
16 | self.set_up_view()
17 | errors = [{"hello": "world"}]
18 | panel_handler = ErrorQuickPanelHandler(self.view, errors)
19 | self.assertEqual(self.view, panel_handler.view)
20 | self.assertEqual(errors, panel_handler.errors)
21 |
22 | def test_items_to_show(self):
23 | """Test that the items are well formatted."""
24 | self.set_up_view()
25 | errors = [
26 | {
27 | "severity": 3,
28 | "error": "ERROR_MSG",
29 | "file": "error_file"
30 | },
31 | {
32 | "severity": 2,
33 | "error": "WARNING_MSG",
34 | "file": "warning_file"
35 | }
36 | ]
37 | panel_handler = ErrorQuickPanelHandler(self.view, errors)
38 | items_to_show = panel_handler.items_to_show()
39 | expected = [["ERROR: ERROR_MSG", "error_file"],
40 | ["WARNING: WARNING_MSG", "warning_file"]]
41 | self.assertEqual(items_to_show, expected)
42 |
43 | def test_on_done(self):
44 | """Test that the items are well formatted."""
45 | self.set_up_view()
46 | errors = [
47 | {
48 | "severity": 3,
49 | "error": "ERROR_MSG",
50 | "file": "error_file",
51 | "row": 0,
52 | "col": 0
53 | },
54 | ]
55 | panel_handler = ErrorQuickPanelHandler(self.view, errors)
56 | self.assertIsNone(panel_handler.on_done(-1))
57 | self.assertIsNone(panel_handler.on_done(1))
58 | view = panel_handler.on_done(0)
59 | self.assertIsNotNone(view)
60 | view.set_scratch(True)
61 | view.window().focus_view(view)
62 | view.window().run_command("close_file")
63 |
--------------------------------------------------------------------------------
/tests/test_row_col.py:
--------------------------------------------------------------------------------
1 | """Tests for classes incapsulating row and column positions."""
2 | import imp
3 | from os import path
4 |
5 | from EasyClangComplete.plugin.utils.subl import row_col
6 | from EasyClangComplete.tests.gui_test_wrapper import GuiTestWrapper
7 |
8 | imp.reload(row_col)
9 |
10 | ZeroIndexedRowCol = row_col.ZeroIndexedRowCol
11 | OneIndexedRowCol = row_col.OneIndexedRowCol
12 |
13 |
14 | class TestRowCol(GuiTestWrapper):
15 | """Test getting flags from CMakeLists.txt."""
16 |
17 | def test_setup_view(self):
18 | """Test that setup view correctly sets up the view."""
19 | file_name = path.join(path.dirname(__file__),
20 | 'test_files',
21 | 'test.cpp')
22 | self.check_view(file_name)
23 |
24 | def test_init(self):
25 | """Initialization test."""
26 | pos = ZeroIndexedRowCol(4, 2)
27 | self.assertEquals(pos.row, 4)
28 | self.assertEquals(pos.col, 2)
29 | self.assertEquals((4, 2), pos.as_tuple())
30 |
31 | def test_init_from_one_indexed(self):
32 | """Initialization test from 1-indexed row and column."""
33 | pos = ZeroIndexedRowCol.from_one_indexed(OneIndexedRowCol(4, 2))
34 | self.assertEquals(pos.row, 3)
35 | self.assertEquals(pos.col, 1)
36 | self.assertEquals((3, 1), pos.as_tuple())
37 |
38 | def test_init_from_zero_indexed(self):
39 | """Initialization test from 0-indexed row and column."""
40 | pos = OneIndexedRowCol.from_zero_indexed(ZeroIndexedRowCol(4, 2))
41 | self.assertEquals(pos.row, 5)
42 | self.assertEquals(pos.col, 3)
43 | self.assertEquals((5, 3), pos.as_tuple())
44 |
45 | def test_location(self):
46 | """Location is valid."""
47 | file_name = path.join(path.dirname(__file__),
48 | 'test_files',
49 | 'test.cpp')
50 | self.set_up_view(file_name)
51 | pos = ZeroIndexedRowCol(4, 2)
52 | self.assertEquals(pos.row, 4)
53 | self.assertEquals(pos.col, 2)
54 | location = pos.as_1d_location(self.view)
55 | pos_from_location = ZeroIndexedRowCol.from_1d_location(
56 | self.view, location)
57 | self.assertEquals(pos.row, pos_from_location.row)
58 | self.assertEquals(pos.col, pos_from_location.col)
59 |
60 | default_location = ZeroIndexedRowCol.from_1d_location(self.view, None)
61 | self.assertEquals(0, default_location.row)
62 | self.assertEquals(0, default_location.col)
63 |
--------------------------------------------------------------------------------
/tests/test_singleton.py:
--------------------------------------------------------------------------------
1 | """Test tools.
2 |
3 | Attributes:
4 | easy_clang_complete (module): this plugin module
5 | SublBridge (SublBridge): class for subl bridge
6 | """
7 | import imp
8 | from unittest import TestCase
9 |
10 | from EasyClangComplete.plugin.utils import singleton
11 |
12 |
13 | imp.reload(singleton)
14 |
15 | singleton = singleton.singleton
16 |
17 |
18 | class test_singleton(TestCase):
19 | """Test other things."""
20 |
21 | def test_singleton(self):
22 | """Test if singleton returns a unique reference."""
23 | @singleton
24 | class A(object):
25 | """Class A."""
26 | pass
27 |
28 | @singleton
29 | class B(object):
30 | """Class B different from class A."""
31 | pass
32 |
33 | a = A()
34 | aa = A()
35 | b = B()
36 | bb = B()
37 | self.assertEqual(id(a), id(aa))
38 | self.assertEqual(id(b), id(bb))
39 | self.assertNotEqual(id(a), id(b))
40 |
--------------------------------------------------------------------------------
/tests/test_style.py:
--------------------------------------------------------------------------------
1 | """Test conformance to pep8 and pep257."""
2 | from unittest import TestCase
3 | from os import path
4 |
5 | from EasyClangComplete.plugin.utils.tools import Tools
6 |
7 | PEP_257_IGNORE = [
8 | "D209",
9 | "D203",
10 | "D204",
11 | "D213",
12 | "D406",
13 | "D407"
14 | ]
15 |
16 | PEP257_CMD = "pep257 '{}' --match-dir='^(?!clang|external).*' --ignore={}"
17 | PEP8_CMD = 'pycodestyle --exclude=clang,external,.git '\
18 | '--show-source --show-pep8 --count --max-line-length=80 "{}"'
19 |
20 | PLUGIN_SOURCE_FOLDER = path.dirname(path.dirname(__file__))
21 |
22 | LINUX_MISSING_MSG = "command not found"
23 | WINDOWS_MISSING_MSG = "is not recognized as an internal or external command"
24 |
25 |
26 | class TestStyle(TestCase):
27 | """Test that the code conforms to pep8 and pep257."""
28 |
29 | def test_pep8(self):
30 | """Test conformance to pep8."""
31 | self.maxDiff = None
32 | cmd = PEP8_CMD.format(PLUGIN_SOURCE_FOLDER)
33 | output = Tools.run_command(cmd, shell=True)
34 | if LINUX_MISSING_MSG in output or WINDOWS_MISSING_MSG in output:
35 | print('no pep8 found in path!')
36 | return
37 | self.assertEquals(output, "")
38 |
39 | def test_pep257(self):
40 | """Test conformance to pep257."""
41 | self.maxDiff = None
42 | cmd = PEP257_CMD.format(PLUGIN_SOURCE_FOLDER, ','.join(PEP_257_IGNORE))
43 | output = Tools.run_command(cmd, shell=True)
44 | if LINUX_MISSING_MSG in output or WINDOWS_MISSING_MSG in output:
45 | print('no pep257 found in path!')
46 | return
47 | self.assertEquals(output, "")
48 |
--------------------------------------------------------------------------------
/tests/test_subl_bridge.py:
--------------------------------------------------------------------------------
1 | """Test tools.
2 |
3 | Attributes:
4 | easy_clang_complete (module): this plugin module
5 | SublBridge (SublBridge): class for subl bridge
6 | """
7 | import imp
8 | from os import path
9 |
10 | from EasyClangComplete.plugin.settings import settings_manager
11 | from EasyClangComplete.plugin.utils.subl import subl_bridge
12 |
13 | from EasyClangComplete.tests.gui_test_wrapper import GuiTestWrapper
14 |
15 |
16 | imp.reload(settings_manager)
17 | imp.reload(subl_bridge)
18 |
19 | SettingsManager = settings_manager.SettingsManager
20 |
21 | SublBridge = subl_bridge.SublBridge
22 | PosStatus = subl_bridge.PosStatus
23 |
24 |
25 | class test_tools_command(GuiTestWrapper):
26 | """Test sublime commands."""
27 |
28 | def set_text(self, string):
29 | """Set text to a view.
30 |
31 | Args:
32 | string (str): some string to set
33 | """
34 | self.view.run_command("insert", {"characters": string})
35 |
36 | def move(self, dist, forward=True):
37 | """Move the cursor by distance.
38 |
39 | Args:
40 | dist (int): pixels to move
41 | forward (bool, optional): forward or backward in the file
42 |
43 | """
44 | for _ in range(dist):
45 | self.view.run_command("move",
46 | {"by": "characters", "forward": forward})
47 |
48 | def test_next_line(self):
49 | """Test returning next line."""
50 | self.set_up_view()
51 | self.set_text("hello\nworld!")
52 | self.move(10, forward=False)
53 | next_line = SublBridge.next_line(self.view)
54 | self.assertEqual(next_line, "world!")
55 |
56 | def test_wrong_triggers(self):
57 | """Test that we don't complete on numbers and wrong triggers."""
58 | self.set_up_view(path.join(path.dirname(__file__),
59 | 'test_files',
60 | 'test_wrong_triggers.cpp'))
61 | # Load the completions.
62 | manager = SettingsManager()
63 | settings = manager.user_settings()
64 |
65 | # Check the current cursor position is completable.
66 | self.assertEqual(self.get_row(2), " a > 2.")
67 |
68 | # check that '>' does not trigger completions
69 | pos = self.view.text_point(2, 5)
70 | current_word = self.view.substr(self.view.word(pos))
71 | self.assertEqual(current_word, "> ")
72 | status = SublBridge.get_pos_status(pos, self.view, settings)
73 |
74 | # Verify that we got the expected completions back.
75 | self.assertEqual(status, PosStatus.WRONG_TRIGGER)
76 |
77 | # check that 'a' does not trigger completions
78 | pos = self.view.text_point(2, 3)
79 | current_word = self.view.substr(self.view.word(pos))
80 | self.assertEqual(current_word, "a")
81 |
82 | status = SublBridge.get_pos_status(pos, self.view, settings)
83 |
84 | # Verify that we got the expected completions back.
85 | self.assertEqual(status, PosStatus.COMPLETION_NOT_NEEDED)
86 |
87 | # check that '2.' does not trigger completions
88 | pos = self.view.text_point(2, 8)
89 | current_word = self.view.substr(self.view.word(pos))
90 | self.assertEqual(current_word, ".\n")
91 |
92 | status = SublBridge.get_pos_status(pos, self.view, settings)
93 |
94 | # Verify that we got the expected completions back.
95 | self.assertEqual(status, PosStatus.WRONG_TRIGGER)
96 |
--------------------------------------------------------------------------------
/tests/test_thread_pool.py:
--------------------------------------------------------------------------------
1 | """Test delayed thread pool."""
2 | import time
3 | from unittest import TestCase
4 |
5 | import EasyClangComplete.plugin.utils.thread_pool
6 | import EasyClangComplete.plugin.utils.thread_job
7 |
8 | ThreadPool = EasyClangComplete.plugin.utils.thread_pool.ThreadPool
9 | ThreadJob = EasyClangComplete.plugin.utils.thread_job.ThreadJob
10 |
11 |
12 | def run_me(result):
13 | """Run this asyncronously."""
14 | time.sleep(0.2)
15 | return result
16 |
17 |
18 | TIMEOUT = 5.0
19 |
20 |
21 | class TestContainer():
22 | """A test container to store results of the operation."""
23 |
24 | def __init__(self):
25 | """Initialize this object."""
26 | self.futures = []
27 |
28 | def on_job_done(self, future):
29 | """Call this when the job is done."""
30 | self.futures.append(future)
31 |
32 | def wait_until_got_number_of_callbacks(self, number):
33 | """Wait until callback is called."""
34 | slept = 0.0
35 | time_step = 0.1
36 | while not len(self.futures) == number and slept < TIMEOUT:
37 | time.sleep(time_step)
38 | slept += time_step
39 |
40 |
41 | class TestThreadPool(TestCase):
42 | """Test thread pool."""
43 |
44 | def test_single_job(self):
45 | """Test single job."""
46 | test_container = TestContainer()
47 | job = ThreadJob(name="test_job",
48 | callback=test_container.on_job_done,
49 | function=run_me,
50 | args=[True])
51 | pool = ThreadPool()
52 | pool.new_job(job)
53 | test_container.wait_until_got_number_of_callbacks(1)
54 | self.assertGreater(len(test_container.futures), 0)
55 | self.assertFalse(test_container.futures[0].cancelled())
56 | self.assertTrue(test_container.futures[0].result())
57 |
58 | def test_override_job(self):
59 | """Test overriding job.
60 |
61 | The first job should be overridden by the next one.
62 | """
63 | test_container = TestContainer()
64 | job_1 = ThreadJob(name="test_job",
65 | function=run_me,
66 | callback=test_container.on_job_done,
67 | args=["job_1"])
68 | job_2 = ThreadJob(name="test_job",
69 | function=run_me,
70 | callback=test_container.on_job_done,
71 | args=["job_2"])
72 | job_3 = ThreadJob(name="test_job",
73 | function=run_me,
74 | callback=test_container.on_job_done,
75 | args=["job_3"])
76 | pool = ThreadPool()
77 | pool.new_job(job_1)
78 | pool.new_job(job_2)
79 | pool.new_job(job_3)
80 | test_container.wait_until_got_number_of_callbacks(3)
81 | self.assertEqual(len(test_container.futures), 3)
82 | # Here is what happens. job_1 runs so cannot be cancelled by job_2, so
83 | # job_1 keeps running while job_2 is added to the queue. Then we add
84 | # job_3, which cancels job_2, which immediately calls it's callback,
85 | # thus the first future in the result is from job_2. Then job_1
86 | # eventually finishes. Then job_3 starts and finishes.
87 | self.assertTrue(test_container.futures[0].cancelled())
88 | self.assertFalse(test_container.futures[1].cancelled())
89 | self.assertEqual(test_container.futures[1].result(), "job_1")
90 | self.assertFalse(test_container.futures[2].cancelled())
91 | self.assertEqual(test_container.futures[2].result(), "job_3")
92 |
--------------------------------------------------------------------------------
/tests/test_tools.py:
--------------------------------------------------------------------------------
1 | """Test tools.
2 |
3 | Attributes:
4 | easy_clang_complete (module): this plugin module
5 | SublBridge (SublBridge): class for subl bridge
6 | """
7 | import imp
8 | from unittest import TestCase
9 | from os import path
10 |
11 | from EasyClangComplete.plugin.utils import tools
12 | from EasyClangComplete.plugin.utils import file
13 |
14 | imp.reload(tools)
15 | imp.reload(file)
16 |
17 | File = file.File
18 | Tools = tools.Tools
19 |
20 | PKG_NAME = tools.PKG_NAME
21 |
22 |
23 | class test_tools(TestCase):
24 | """Test other things."""
25 |
26 | def test_pkg_name(self):
27 | """Test if the package name is correct."""
28 | self.assertEqual(PKG_NAME, "EasyClangComplete")
29 |
30 | def test_seconds_from_string(self):
31 | """Test that we can convert time to seconds."""
32 | self.assertEqual(60, Tools.seconds_from_string('00:00:60'))
33 | self.assertEqual(60, Tools.seconds_from_string('00:01:00'))
34 | self.assertEqual(120, Tools.seconds_from_string('00:02:00'))
35 | self.assertEqual(60 * 60, Tools.seconds_from_string('01:00:00'))
36 | self.assertEqual(60 * 60 + 1, Tools.seconds_from_string('01:00:01'))
37 |
38 | def test_run_command(self):
39 | """Test if the commands are run correctly."""
40 | import platform
41 | if platform.system() == 'Windows':
42 | return
43 | temp_dir = File.get_temp_dir()
44 | temp_file_name = 'test_run_command.log'
45 | temp_file_path = path.join(temp_dir, temp_file_name)
46 | if path.exists(temp_file_path):
47 | import os
48 | os.remove(temp_file_path)
49 | self.assertFalse(path.exists(temp_file_path))
50 | cmd_list = ['touch', temp_file_name]
51 | Tools.run_command(cmd_list, cwd=temp_dir)
52 | self.assertTrue(path.exists(temp_file_path))
53 | cmd = 'rm {}'.format(temp_file_path)
54 | Tools.run_command(cmd, shell=True)
55 | self.assertFalse(path.exists(temp_file_path))
56 |
--------------------------------------------------------------------------------
/tests/test_unique_list.py:
--------------------------------------------------------------------------------
1 | """Test compilation database flags generation."""
2 | from unittest import TestCase
3 |
4 | from EasyClangComplete.plugin.utils.unique_list import UniqueList
5 |
6 |
7 | class test_unique_list(TestCase):
8 | """Test unique list."""
9 | def test_init(self):
10 | """Test initialization."""
11 | unique_list = UniqueList()
12 | self.assertEqual([], unique_list.as_list())
13 | self.assertEqual("[]", str(unique_list))
14 | unique_list = UniqueList([1, 2, 3])
15 | self.assertEqual([1, 2, 3], unique_list.as_list())
16 | self.assertEqual("[1, 2, 3]", str(unique_list))
17 |
18 | def test_append(self):
19 | """Test appending single values to unique list."""
20 | unique_list = UniqueList()
21 | unique_list.append(1)
22 | self.assertEqual([1], unique_list.as_list())
23 | unique_list.append(3)
24 | self.assertEqual([1, 3], unique_list.as_list())
25 | unique_list.append(1)
26 | self.assertEqual([1, 3], unique_list.as_list())
27 | unique_list.append(2)
28 | self.assertEqual([1, 3, 2], unique_list.as_list())
29 |
30 | def test_clear(self):
31 | """Test clearing the list."""
32 | unique_list = UniqueList([1, 2, 3])
33 | self.assertEqual([1, 2, 3], unique_list.as_list())
34 | unique_list.clear()
35 | self.assertEqual([], unique_list.as_list())
36 |
37 | def test_iterable(self):
38 | """Test iterating over values."""
39 | unique_list = UniqueList([0, 1, 2])
40 | counter = 0
41 | for i in unique_list:
42 | self.assertEqual(i, counter)
43 | counter += 1
44 |
45 | def test_add(self):
46 | """Test merging with other iterable."""
47 | unique_list = UniqueList([1, 2, 3])
48 | other_list = [1, 4, 2, 5]
49 | unique_list += other_list
50 | self.assertEqual([1, 2, 3, 4, 5], unique_list.as_list())
51 |
--------------------------------------------------------------------------------
/unittesting.json:
--------------------------------------------------------------------------------
1 | {
2 | "tests_dir" : "tests",
3 | "pattern" : "test*.py",
4 | "async": true,
5 | "deferred": false,
6 | "verbosity": 10,
7 | "reload_package_on_testing": true,
8 | "show_reload_progress": true,
9 | "output": "",
10 | "capture_console": true
11 | }
12 |
--------------------------------------------------------------------------------