├── .github
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
├── ci-gradle.properties
├── ci-reporter.yml
├── labels.json
├── no-response.yml
├── stale.yml
└── workflows
│ └── ci.yml
├── .gitignore
├── .idea
├── checkstyle-idea.xml
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
└── copyright
│ ├── Apache_2_0.xml
│ └── profiles_settings.xml
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── RELEASING.md
├── art
├── actions1.png
├── actions2.png
├── pylint-inspection-severity.png
├── pylint-pycharm.png
└── pylint-settings.png
├── build.gradle
├── config
└── checkstyle
│ ├── checkstyle-suppressions.xml
│ └── checkstyle.xml
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── src
└── main
│ ├── java
│ └── com
│ │ └── leinardi
│ │ └── pycharm
│ │ └── pylint
│ │ ├── PylintAnnotator.java
│ │ ├── PylintBatchInspection.java
│ │ ├── PylintBundle.java
│ │ ├── PylintConfigService.java
│ │ ├── PylintConfigurable.java
│ │ ├── PylintPlugin.java
│ │ ├── actions
│ │ ├── BaseAction.java
│ │ ├── ClearAll.java
│ │ ├── Close.java
│ │ ├── CollapseAll.java
│ │ ├── DisplayConvention.java
│ │ ├── DisplayErrors.java
│ │ ├── DisplayInfo.java
│ │ ├── DisplayRefactor.java
│ │ ├── DisplayWarnings.java
│ │ ├── ExpandAll.java
│ │ ├── ScanCurrentChangeList.java
│ │ ├── ScanCurrentFile.java
│ │ ├── ScanEverythingAction.java
│ │ ├── ScanModifiedFiles.java
│ │ ├── ScanModule.java
│ │ ├── ScanProject.java
│ │ ├── ScanSourceRootsAction.java
│ │ ├── ScrollToSource.java
│ │ ├── Settings.java
│ │ ├── StopCheck.java
│ │ └── ToolWindowAccess.java
│ │ ├── checker
│ │ ├── CreateScannableFileAction.java
│ │ ├── Problem.java
│ │ ├── PsiFileValidator.java
│ │ ├── ScanFiles.java
│ │ ├── ScannableFile.java
│ │ ├── ScannerListener.java
│ │ └── UiFeedbackScannerListener.java
│ │ ├── exception
│ │ ├── PylintPluginException.java
│ │ ├── PylintPluginParseException.java
│ │ ├── PylintServiceException.java
│ │ └── PylintToolException.java
│ │ ├── handlers
│ │ ├── ScanFilesBeforeCheckinHandler.java
│ │ └── ScanFilesBeforeCheckinHandlerFactory.java
│ │ ├── plapi
│ │ ├── Issue.java
│ │ ├── ProcessResultsThread.java
│ │ ├── PylintRunner.java
│ │ └── SeverityLevel.java
│ │ ├── toolwindow
│ │ ├── PylintToolWindowFactory.java
│ │ ├── PylintToolWindowPanel.java
│ │ ├── ResultTreeModel.java
│ │ ├── ResultTreeNode.java
│ │ ├── ResultTreeRenderer.java
│ │ └── TogglableTreeNode.java
│ │ ├── ui
│ │ ├── PylintConfigPanel.form
│ │ └── PylintConfigPanel.java
│ │ └── util
│ │ ├── Async.java
│ │ ├── Exceptions.java
│ │ ├── FileTypes.java
│ │ ├── Icons.java
│ │ ├── Notifications.java
│ │ ├── OS.java
│ │ ├── PyPackageManagerUtil.java
│ │ ├── Strings.java
│ │ ├── TempDirProvider.java
│ │ └── VfUtil.java
│ └── resources
│ ├── META-INF
│ └── plugin.xml
│ ├── com
│ └── leinardi
│ │ └── pycharm
│ │ └── pylint
│ │ ├── PylintBundle.properties
│ │ └── images
│ │ ├── pylint.png
│ │ ├── pylint@2x.png
│ │ ├── pylint@2x_dark.png
│ │ ├── pylint_dark.png
│ │ ├── pythonFile.png
│ │ └── pythonFile@2x.png
│ └── inspectionDescriptions
│ └── Pylint.html
└── versions-plugin.gradle
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, gender identity and expression, level of experience,
9 | education, socio-economic status, nationality, personal appearance, race,
10 | religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at roberto@leinardi.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 | Considering that this project is actively maintained, contributions of all types are welcome.
3 |
4 |
5 | ## Opening issues
6 | Open a new issue when:
7 | - you notice an unwanted behavior
8 | - you want a new feature implemented
9 | - you have just some doubts
10 |
11 | To open a new issue, please use the provided issue template and fill it out as much as possible.
12 | If you are interested to an existing issue, feel free to comment the issue or subscribe to it.
13 |
14 |
15 | ## Submitting pull requests
16 | If you want to fix a bug or implement a new feature, feel free to submit a new pull request.
17 | To submit a pull request, you have to fork this repository and fill the PR template.
18 | When you want to submit a pull request, remember to:
19 | - follow this project's code style
20 | - run `./gradlew clean check`
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 |
12 | ### Step 1: Are you in the right place?
13 | - [ ] I have verified there are no duplicate active or recent bugs, questions, or requests
14 | - [ ] I have verified that I am using the latest version of the plugin.
15 |
16 | ### Step 2: Describe your environment
17 | - Plugin version: `?`
18 | - PyCharm/IDEA version: `?`
19 | - Pylint version: `?`
20 |
21 | ### Step 3: Describe the problem:
22 | #### Steps to reproduce:
23 |
24 | 1. _____
25 | 2. _____
26 | 3. _____
27 |
28 |
31 | #### Observed Results:
32 |
33 | *
34 |
35 |
38 | #### Expected Results:
39 |
40 | *
41 |
42 | #### Relevant Code:
43 |
46 | ```java
47 | System.out.println("Hello, world!");
48 | ```
49 |
50 |
54 | ```Gradle
55 | java.lang.RuntimeException: This is an example Exception log
56 | at com.leinardi.HelloWorld
57 | at com.leinardi.HelloWorld$ThisIsNotARealLog
58 | at bigcorporate.app.Instrumentation.callActivityOnResume(Instrumentation.kt)
59 | ```
60 |
61 |
64 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | ### First time contributor checklist
7 |
8 | - [ ] I have read [how to contribute](/.github/CONTRIBUTING.md) to this project
9 | - [ ] I have read [the code of conduct](/.github/CODE_OF_CONDUCT.md) to this project
10 |
11 | ### Contributor checklist
12 |
13 | - [ ] I am targeting the `master` branch (and **not** the `release` branch)
14 | - [ ] I am using the provided [codeStyleConfig.xml](/.idea/codeStyles)
15 | - [ ] I have tested my contribution on these versions of PyCharm/IDEA:
16 | * PyCharm Community XXXX.Y.Z
17 | * IntelliJ IDEA XXXX.Y.Z
18 | - [ ] My contribution is fully baked and ready to be merged as is
19 | - [ ] I ensure that all the open issues my contribution fixes are mentioned in the commit message of my first commit
20 | using the `Fixes #1234` [syntax](https://help.github.com/articles/closing-issues-using-keywords/)
21 |
22 | ----------
23 |
24 | ### Description
25 |
30 |
31 | ### Type of Changes
32 |
33 | | | Type |
34 | | ------------- | ------------- |
35 | | ✓ | :bug: Bug fix |
36 | | ✓ | :sparkles: New feature |
37 | | ✓ | :hammer: Refactoring |
38 | | ✓ | :scroll: Docs |
39 |
40 | ### Related Issue
41 |
42 |
48 |
--------------------------------------------------------------------------------
/.github/ci-gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2023 Roberto Leinardi.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # https://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 |
17 | org.gradle.daemon=false
18 | org.gradle.workers.max=2
19 |
--------------------------------------------------------------------------------
/.github/ci-reporter.yml:
--------------------------------------------------------------------------------
1 | # Set to false to create a new comment instead of updating the app's first one
2 | updateComment: true
3 |
4 | # Use a custom string, or set to false to disable
5 | before: "Unfortunately, the [{{ provider }} build]({{ targetUrl }}) is failing as of {{ commit }}. Here's the output:"
6 |
7 | # Use a custom string, or set to false to disable
8 | after: "If you need help with this issue, don't hesitate to ask a maintainer of the project!"
9 |
--------------------------------------------------------------------------------
/.github/labels.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "Priority: Critical",
4 | "color": "#D32F2F"
5 | },
6 | {
7 | "name": "Priority: High",
8 | "color": "#FF9800"
9 | },
10 | {
11 | "name": "Priority: Low",
12 | "color": "#4CAF50"
13 | },
14 | {
15 | "name": "Priority: Medium",
16 | "color": "#CDDC39"
17 | },
18 | {
19 | "name": "Status: Abandoned",
20 | "color": "#000000"
21 | },
22 | {
23 | "name": "Status: Accepted",
24 | "color": "#4CAF50"
25 | },
26 | {
27 | "name": "Status: Available",
28 | "color": "#C8E6C9"
29 | },
30 | {
31 | "name": "Status: Blocked",
32 | "color": "#D32F2F"
33 | },
34 | {
35 | "name": "Status: Completed",
36 | "color": "#009688"
37 | },
38 | {
39 | "name": "Status: In Progress",
40 | "color": "#E0E0E0"
41 | },
42 | {
43 | "name": "Status: Info needed",
44 | "color": "#5C6BC0"
45 | },
46 | {
47 | "name": "Status: On Hold",
48 | "color": "#D32F2F"
49 | },
50 | {
51 | "name": "Status: Pending",
52 | "color": "#FFF176"
53 | },
54 | {
55 | "name": "Status: Review Needed",
56 | "color": "#CDDC39"
57 | },
58 | {
59 | "name": "Status: Revision Needed",
60 | "color": "#D32F2F"
61 | },
62 | {
63 | "name": "Status: Stale",
64 | "color": "#9E9E9E"
65 | },
66 | {
67 | "name": "triage",
68 | "color": "#81D4FA"
69 | },
70 | {
71 | "name": "Type: Bug",
72 | "color": "#D32F2F"
73 | },
74 | {
75 | "name": "Type: Enhancement",
76 | "color": "#546E7A"
77 | },
78 | {
79 | "name": "Type: Maintenance",
80 | "color": "#CDDC39"
81 | },
82 | {
83 | "name": "Type: Question",
84 | "color": "#673AB7"
85 | }
86 | ]
87 |
--------------------------------------------------------------------------------
/.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: 21
5 | # Label requiring a response
6 | responseRequiredLabel: "Status: Info needed"
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 reach out if you have or find the answers we need so
13 | that we can investigate further.
14 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Configuration for probot-stale - https://github.com/probot/stale
2 |
3 | # Number of days of inactivity before an Issue or Pull Request becomes stale
4 | daysUntilStale: 60
5 |
6 | # Number of days of inactivity before a stale Issue or Pull Request is closed.
7 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
8 | daysUntilClose: false
9 |
10 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
11 | exemptLabels:
12 | - pinned
13 | - security
14 |
15 | # Set to true to ignore issues in a project (defaults to false)
16 | exemptProjects: false
17 |
18 | # Set to true to ignore issues in a milestone (defaults to false)
19 | exemptMilestones: false
20 |
21 | # Label to use when marking as stale
22 | staleLabel: "Status: Stale"
23 |
24 | # Comment to post when marking as stale. Set to `false` to disable
25 | markComment: >
26 | This issue has been automatically marked as stale because it has not had activity in the last 60 days.
27 |
28 | # Comment to post when removing the stale label.
29 | # unmarkComment: >
30 | # Your comment here.
31 |
32 | # Comment to post when closing a stale Issue or Pull Request.
33 | # closeComment: >
34 | # Your comment here.
35 |
36 | # Limit the number of actions per hour, from 1-30. Default is 30
37 | limitPerRun: 30
38 |
39 | # Limit to only `issues` or `pulls`
40 | # only: issues
41 |
42 | # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
43 | # pulls:
44 | # daysUntilStale: 30
45 | # markComment: >
46 | # This pull request has been automatically marked as stale because it has not had
47 | # recent activity. It will be closed if no further activity occurs. Thank you
48 | # for your contributions.
49 |
50 | # issues:
51 | # exemptLabels:
52 | # - confirmed
53 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | pull_request:
5 | paths-ignore:
6 | - '**.md'
7 | push:
8 | branches:
9 | - master
10 | - release
11 | paths-ignore:
12 | - '**.md'
13 | workflow_dispatch:
14 |
15 | # This allows a subsequently queued workflow run to interrupt previous runs
16 | concurrency:
17 | group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
18 | cancel-in-progress: true
19 |
20 | jobs:
21 | build:
22 | name: Build
23 | runs-on: ubuntu-latest
24 | timeout-minutes: 10
25 | env:
26 | TERM: dumb
27 |
28 | steps:
29 | - name: Checkout
30 | uses: actions/checkout@v4
31 | with:
32 | fetch-depth: 0
33 |
34 | - name: Setup JDK
35 | uses: actions/setup-java@v4
36 | with:
37 | distribution: 'temurin'
38 | java-version: 17.0.10
39 |
40 | - name: Setup Gradle
41 | uses: gradle/actions/setup-gradle@v4
42 |
43 | - name: Copy CI gradle.properties
44 | run: mkdir -p ~/.gradle ; cp .github/ci-gradle.properties ~/.gradle/gradle.properties
45 |
46 | - name: Validate gradle wrapper
47 | uses: gradle/wrapper-validation-action@v1
48 |
49 | ## Actual task
50 | - name: Check and build
51 | run: ./gradlew check buildPlugin
52 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/.DS_Store
2 | .idea/*
3 | !.idea/codeStyles/
4 | !.idea/copyright/
5 | !.idea/checkstyle-idea.xml
6 | **/*.iml
7 | .gradle/
8 | **/build/
9 | **/out/
10 |
--------------------------------------------------------------------------------
/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 8.29
5 | JavaOnly
6 |
7 |
9 |
10 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/copyright/Apache_2_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk: openjdk8
3 | sudo: true
4 |
5 | os:
6 | - linux
7 | addons:
8 | apt_packages:
9 | - pandoc
10 |
11 | before_cache:
12 | # Do not cache a few Gradle files/directories (see https://docs.travis-ci.com/user/languages/java/#Caching)
13 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
14 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
15 |
16 | cache:
17 | directories:
18 | # Gradle dependencies
19 | - $HOME/.gradle/caches/
20 | - $HOME/.gradle/wrapper/
21 |
22 | install:
23 | - true
24 |
25 | before_script:
26 | - sed -i -e 's/pycharmPath=/#pycharmPath=/g' gradle.properties
27 | - sed -i -e 's/#pythonPlugin=/pythonPlugin=/g' gradle.properties
28 |
29 | script:
30 | - set -o pipefail
31 | - ./gradlew clean check --profile --continue 2>&1 | tee build.log
32 | - set +o pipefail
33 | - |
34 | if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
35 | ./gradlew violationCommentsToGitHub -DGITHUB_PULLREQUESTID=$TRAVIS_PULL_REQUEST -DGITHUB_OAUTH2TOKEN=$GITHUB_OAUTH2TOKEN --info
36 | fi
37 | - pandoc `ls -1rt build/reports/profile/profile-*.html | tail -n1` -t plain
38 | - ./gradlew dependencyUpdate
39 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | **[0.16.4] 2024-10-05**
2 |
3 | - Defined action update thread for actions for ScrollToSource
4 |
5 | **[0.16.3] 2024-10-05**
6 |
7 | - Fix #103 #105: Defined action update thread for actions
8 | - New: Min IDEA version raised from PC-2022.1.4 to PC-2023.3.6
9 | - Several dependency updates
10 |
11 | **[0.16.2] 2023-10-16**
12 |
13 | - Fix compatibility issues
14 |
15 | **[0.16.1] 2023-10-09**
16 |
17 | - Fix several compatibility issues
18 |
19 | **[0.16.0] 2023-09-02**
20 |
21 | - Possible fixe for #82: Pylint doesn't detect remote interpreter
22 | - Possible fixe for #58: On Windows allow pylint to use pylint installed in WSL
23 | - Respect Pylint path field and don't force usage of project interpreter
24 |
25 | **[0.15.0] 2023-04-24**
26 |
27 | - Fixed Icons not visible in new Jetbrains UI
28 | - New: Min IDEA version raised from PC-2021.2 to PC-2022.1.4
29 | - Several dependency updates
30 |
31 | **[0.14.0] 2022-02-26**
32 |
33 | - New: Improved executable auto-detection on Windows
34 | - New: Make plugin hot-reloadable
35 | - New: Show notification when PyLint exits abnormally
36 | - Several dependency updates
37 |
38 | **[0.13.1] 2021-12-06**
39 |
40 | - New: Minimum compatibility version raised to 201.8743
41 |
42 | **[0.13.0] 2021-12-05**
43 |
44 | - Fixed #11: Stopping old instances of PyLint when requesting new ones (a huge thanks to @intgr for fixing this issue
45 | for [mypy-pycharm](https://github.com/leinardi/mypy-pycharm), making the port for this plugin trivial!)
46 | - New: Min IDEA version raised from 2018 to PC-2021.2.3
47 | - Several dependency updates
48 |
49 | **[0.12.2] 2020-04-25**
50 |
51 | - Fixed #61: Changed module/project icons to be compatible with EAPs of IDEA 2020.1
52 |
53 | **[0.12.1] 2020-02-04**
54 |
55 | - Fixed regression generating several errors in Event Log during inspection
56 |
57 | **[0.12.0] 2020-02-01**
58 |
59 | - New: Min IDEA version raised from 2016 to 2018
60 | - New: Tidied up deprecations in the 2018 SDK
61 | - New: Fixed possible deadlock during inspection
62 |
63 | **[0.11.2] 2020-02-01**
64 |
65 | - Fix #42: no linting when using `--init-hook` in the parameter field
66 |
67 | **[0.11.1] 2019-09-15**
68 |
69 | - New: Improved error handling
70 |
71 | **[0.11.0] 2019-01-02**
72 |
73 | - PyLint real-time inspection disabled by default as numerous users find running it in the background has a negative
74 | impact on their system performance
75 | - Fix #29: Implementing a better virtualenv detection
76 |
77 | **[0.10.2] 2018-09-25**
78 |
79 | - Fix #26: SyntaxError: Non-UTF-8 code starting with '\x90' when interpreter is set on Windows
80 |
81 | **[0.10.1] 2018-09-21**
82 |
83 | - Fix #22: PyLint absolute path not working on Windows
84 | - Fix #24: PyLint auto-detection not working on Windows
85 |
86 | **[0.10.0] 2018-09-12**
87 |
88 | - Fix #7: Support linting inside current Virtualenv
89 | - Fix #19: Don't show the 'syntax-error' message for real-time scan
90 | - New: Improved Pylint auto-detection
91 | - New: Option to install Pylint if missing
92 | - New: Settings button now opens File | Settings | Pylint
93 | - New: Minimum compatibility version raised to 163.15529
94 |
95 | **[0.9.0] 2018-09-04**
96 |
97 | - Info: I am aware of the venv import error but for now I only have a partial solution. If you want to help or just get
98 | updates on the issue, click [here](https://github.com/leinardi/pylint-pycharm/issues/7).
99 | - New: Showing better info to the user if Pylint is missing
100 | - New: Added ability to optionally specify a pylintrc
101 | - New: Added ability to optionally specify Pylint arguments
102 |
103 | **[0.8.0] 2018-09-01**
104 |
105 | - New: Added missing type `info`
106 | - New: Autoscroll to Source is disabled by default
107 |
108 | **[0.7.1] 2018-09-01**
109 |
110 | - New: Project has moved to [https://github.com/leinardi/pylint-pycharm](https://github.com/leinardi/pylint-pycharm)
111 |
112 | **[0.7.0] 2018-08-31**
113 |
114 | - New: Added Scan Files Before Checkin
115 | - New: Added real-time scanning!
116 | - New: UX based on Checkstyle-IDEA plugin.
117 | - New: Plugin id and name changed (please remove manually the old plugin)
118 |
119 | **[0.1.0]**
120 |
121 | - Initial release.
122 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pylint-pycharm
2 | [](https://github.com/leinardi/pylint-pycharm/releases)
3 | [](https://travis-ci.org/leinardi/pylint-pycharm)
4 | [](https://github.com/leinardi/pylint-pycharm/blob/master/LICENSE)
5 | [](https://github.com/leinardi/pylint-pycharm/stargazers)
6 |
7 | This plugin provides both real-time and on-demand scanning of Python files with Pylint from within PyCharm/IDEA.
8 |
9 | Pylint is a Python source code analyzer which looks for programming errors,
10 | helps enforcing a coding standard and sniffs for some code smells
11 | (as defined in Martin Fowler's Refactoring book).
12 |
13 | 
14 |
15 | ## Installation steps
16 | 1. In the **Settings/Preferences** dialog (CTRL+Alt+S), click **Plugins**. The [Plugins page](https://www.jetbrains.com/help/pycharm/plugins-settings.html) opens.
17 | 2. Click **Browse repositories**.
18 | 3. In the [Browse Repositories dialog](https://www.jetbrains.com/help/pycharm/browse-repositories-dialog.html) that opens, right-click on the plugin named **Pylint** and select **Download and Install**.
19 | 4. Confirm your intention to download and install the selected plugin.
20 | 5. Click **Close**.
21 | 6. Click **OK** in the **Settings** dialog and restart PyCharm for the changes to take effect.
22 |
23 | ## Configuration
24 |
25 | The only configuration needed is to set the path to Pylint executable, and only if is not already
26 | inside the PATH environment variable.
27 |
28 | To reach the Plugin configuration screen you can open **Settings/Preferences** dialog (CTRL+Alt+S), click **Other Settings** and then **Pylint** or simply click the gear icon from the side bar of the Pylint tool window.
29 |
30 | To change the path to your Pylint executable you can either type the path directly or use
31 | the Browse button to open a file selection dialog.
32 |
33 | Once you changed the path you should press the Test button to check if the plugin is able to run
34 | the executable.
35 |
36 | 
37 |
38 | ### Real-time inspection disabled by default
39 | The plugin real-time inspection is disabled by default as numerous users find running `mix credo` in the background has
40 | a negative impact on their system performance. If you like to try enabling the annotation, you can turn it on:
41 |
42 | 1. Preferences > Editor > Inspections > Pylint
43 | 2. Check "Pylint real-time scan"
44 |
45 | ### Inspection severity
46 |
47 | By default, Pylint message severity is set to Warning. It is possible to change the severity level
48 | by going to **Settings/Preferences** dialog (CTRL+Alt+S) -> **Editor** -> **Inspections** -> **Pylint** -> **Severity**:
49 |
50 | 
51 |
52 | ## Usage
53 |
54 | 
55 | 
56 |
57 | ## FAQ
58 | ### How can I prevent the code inspection to run on a specific folder?
59 |
60 | The easiest way to ignore a specific folder is to mark it as Excluded from PyCharm/IDEA:
61 |
62 | 1. Open PyCharm/IDEA Settings -> *your project* -> Project structure
63 | 2. Select the directory you want to exclude
64 | 3. Click the Excluded button (red folder icon)
65 |
66 | More info [here](https://www.jetbrains.com/help/pycharm/configuring-folders-within-a-content-root.html#mark).
67 |
68 | ### The name of the plugin is `pylint-pycharm`, can I also use it with IntelliJ IDEA?
69 |
70 | This plugin officially supports only PyCharm, but it should work also on IntelliJ IDEA
71 | if you have the [Python Community Edition](https://plugins.jetbrains.com/plugin/7322-python-community-edition)
72 | plugin installed. If it does not work, feel free to open a bug on the [issue tracker](https://github.com/leinardi/pylint-pycharm/issues).
73 |
74 | ### I like this plugin, how can I support it?
75 |
76 | The best way to support this plugin is to rate it on the [JetBrains Plugin Repository page](https://plugins.jetbrains.com/plugin/11084-pylint) and to star this project on GitHub.
77 | Feedback is always welcome: if you found a bug or would like to suggest a feature,
78 | feel free to open an issue on the [issue tracker](https://github.com/leinardi/pylint-pycharm/issues). If your feedback doesn't fall in the previous categories,
79 | you can always leave a comment on the [Plugin Repository page](https://plugins.jetbrains.com/plugin/11084-pylint).
80 |
81 | ## Acknowledgements
82 | _If I have seen further it is by standing on the shoulders of Giants - Isaac Newton_
83 |
84 | A huge thanks:
85 | - to the project [CheckStyle-IDEA](https://github.com/jshiell/checkstyle-idea),
86 | which code and architecture I have heavily used when developing this plugin.
87 | - to @intgr, for [the contribution to this project](https://github.com/leinardi/pylint-pycharm/pulls?q=is%3Apr+author%3Aintgr) and to [mypy-pycharm](https://github.com/leinardi/mypy-pycharm/pulls?q=is%3Apr+author%3Aintgr)
88 |
89 | ## License
90 |
91 | ```
92 | Copyright 2021 Roberto Leinardi.
93 |
94 | Licensed to the Apache Software Foundation (ASF) under one or more contributor
95 | license agreements. See the NOTICE file distributed with this work for
96 | additional information regarding copyright ownership. The ASF licenses this
97 | file to you under the Apache License, Version 2.0 (the "License"); you may not
98 | use this file except in compliance with the License. You may obtain a copy of
99 | the License at
100 |
101 | http://www.apache.org/licenses/LICENSE-2.0
102 |
103 | Unless required by applicable law or agreed to in writing, software
104 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
105 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
106 | License for the specific language governing permissions and limitations under
107 | the License.
108 | ```
109 |
--------------------------------------------------------------------------------
/RELEASING.md:
--------------------------------------------------------------------------------
1 | # Releasing
2 |
3 | 1. Bump the `version` property in `gradle.properties` based on Major.Minor.Patch naming scheme
4 | 2. Update `CHANGELOG.md` for the impending release.
5 | 3. Update the `README.md` with the new changes (if necessary).
6 | 4. `./gradlew clean buildPlugin`
7 | 5. `git commit -am "Prepare for release x.y.z"` (where x.y.z is the version you set in step 1)
8 | 6. `git push`
9 | 7. Create a new release on Github
10 | 1. Tag version `x.y.z` (`git tag -s x.y.z && git push --tags`)
11 | 2. Release title `x.y.z`
12 | 3. Paste the content from `CHANGELOG.md` as the description
13 | 4. Upload the `build/distributions/pylint-plugin-x.y.z.zip`
14 | 8. Create a PR from [master](../../tree/master) to [release](../../tree/release)
15 | 9. `./gradlew publishPlugin`
16 |
--------------------------------------------------------------------------------
/art/actions1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leinardi/pylint-pycharm/0db20e71511920c98713b5156d99b2421549ac2c/art/actions1.png
--------------------------------------------------------------------------------
/art/actions2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leinardi/pylint-pycharm/0db20e71511920c98713b5156d99b2421549ac2c/art/actions2.png
--------------------------------------------------------------------------------
/art/pylint-inspection-severity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leinardi/pylint-pycharm/0db20e71511920c98713b5156d99b2421549ac2c/art/pylint-inspection-severity.png
--------------------------------------------------------------------------------
/art/pylint-pycharm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leinardi/pylint-pycharm/0db20e71511920c98713b5156d99b2421549ac2c/art/pylint-pycharm.png
--------------------------------------------------------------------------------
/art/pylint-settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leinardi/pylint-pycharm/0db20e71511920c98713b5156d99b2421549ac2c/art/pylint-settings.png
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Roberto Leinardi.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import org.commonmark.node.Node
18 | import org.commonmark.parser.Parser
19 | import org.commonmark.renderer.html.HtmlRenderer
20 | import se.bjurr.violations.comments.github.plugin.gradle.ViolationCommentsToGitHubTask
21 |
22 | buildscript {
23 | repositories {
24 | mavenCentral()
25 | gradlePluginPortal()
26 | }
27 | dependencies {
28 | classpath 'com.atlassian.commonmark:commonmark:0.17.0'
29 | // NOTE: Do not place your application dependencies here; they belong
30 | // in the individual module build.gradle files
31 | }
32 | }
33 |
34 | plugins {
35 | id 'org.jetbrains.intellij' version '1.17.4'
36 | id 'net.ltgt.errorprone' version '4.0.1'
37 | id 'idea'
38 | id 'java'
39 | id 'checkstyle'
40 | id 'com.github.ben-manes.versions' version '0.51.0'
41 | id 'se.bjurr.violations.violation-comments-to-github-gradle-plugin' version '1.70.0'
42 | }
43 |
44 | checkstyle {
45 | ignoreFailures = false // Whether this task will ignore failures and continue running the build.
46 | configFile rootProject.file('config/checkstyle/checkstyle.xml')
47 | // The Checkstyle configuration file to use.
48 | toolVersion = '9.1' // The version of Checkstyle you want to be used
49 | }
50 |
51 | def hasPycharmPath = project.hasProperty('pycharmPath')
52 | def props = new Properties()
53 | rootProject.file('src/main/resources/com/leinardi/pycharm/pylint/PylintBundle.properties')
54 | .withInputStream {
55 | props.load(it)
56 | }
57 |
58 | gradle.projectsEvaluated {
59 | tasks.withType(JavaCompile).configureEach {
60 | options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
61 | }
62 | }
63 |
64 | group 'com.leinardi.pycharm'
65 | version version
66 |
67 | sourceCompatibility = JavaVersion.VERSION_17
68 | targetCompatibility = JavaVersion.VERSION_17
69 |
70 | intellij {
71 | version = ideVersion
72 | pluginName = props.getProperty('plugin.name').toLowerCase().replace(' ', '-')
73 | downloadSources = Boolean.valueOf(downloadIdeaSources)
74 | updateSinceUntilBuild = true
75 | if (hasPycharmPath) {
76 | alternativeIdePath = pycharmPath
77 | }
78 | plugins = [pythonPlugin]
79 | }
80 |
81 | runIde {
82 | systemProperties.put("idea.log.debug.categories", "#com.leinardi.pycharm.mypy")
83 | // Log verbose information when dynamic plugin unloading fails
84 | systemProperties.put("ide.plugins.snapshot.on.unload.fail", "true")
85 | }
86 |
87 | // Causes error popup when building while sandbox IDE is open. Disable in development
88 | if (System.getenv('DEVELOP')) {
89 | buildSearchableOptions.enabled = false
90 | }
91 |
92 | patchPluginXml {
93 | version = project.property('version')
94 | sinceBuild = project.property('sinceBuild')
95 | untilBuild = project.property('untilBuild')
96 | pluginDescription = props.getProperty('plugin.Pylint-PyCharm.description')
97 | changeNotes = getChangelogHtml()
98 | }
99 |
100 | publishPlugin {
101 | def publishToken = project.hasProperty('jetbrainsPublishToken') ? jetbrainsPublishToken : ""
102 | token.set(publishToken)
103 | channels = [publishChannels]
104 | }
105 |
106 | repositories {
107 | mavenCentral()
108 | gradlePluginPortal()
109 | if (hasPycharmPath) {
110 | flatDir {
111 | dirs "$pycharmPath/lib"
112 | }
113 | }
114 | }
115 |
116 | dependencies {
117 | if (hasPycharmPath) {
118 | compileOnly name: 'pycharm'
119 | }
120 | implementation 'com.squareup.moshi:moshi:1.14.0'
121 | errorprone 'com.google.errorprone:error_prone_core:2.21.1'
122 | }
123 |
124 | def getChangelogHtml() {
125 | Parser parser = Parser.builder().build()
126 | Node document = parser.parseReader(rootProject.file('CHANGELOG.md').newReader())
127 | HtmlRenderer renderer = HtmlRenderer.builder().build()
128 | renderer.render(document.firstChild.next)
129 | }
130 |
131 | check.dependsOn(verifyPlugin)
132 |
133 | task violationCommentsToGitHub(type: ViolationCommentsToGitHubTask) {
134 | repositoryOwner = "leinardi"
135 | repositoryName = "pylint-pycharm"
136 | pullRequestId = System.properties['GITHUB_PULLREQUESTID']
137 | oAuth2Token = System.properties['GITHUB_OAUTH2TOKEN']
138 | gitHubUrl = "https://api.github.com/"
139 | createCommentWithAllSingleFileComments = false
140 | createSingleFileComments = true
141 | commentOnlyChangedContent = true
142 | violations = [
143 | ["FINDBUGS", ".", ".*/reports/findbugs/.*\\.xml\$", "Findbugs"],
144 | ["CHECKSTYLE", ".", ".*/reports/checkstyle/.*debug\\.xml\$", "Checkstyle"],
145 | ["ANDROIDLINT", ".", ".*/reports/lint-results.*\\.xml\$", "Android Lint"],
146 | ["GOOGLEERRORPRONE", ".", ".*/build.log\$", "Error Prone"]
147 | ]
148 | }
149 |
150 | wrapper {
151 | gradleVersion = "8.10.2"
152 | distributionType = Wrapper.DistributionType.ALL
153 | }
154 |
--------------------------------------------------------------------------------
/config/checkstyle/checkstyle-suppressions.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2023 Roberto Leinardi.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # https://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | version=0.16.4
17 | ideVersion=PC-2023.3.6
18 | pythonPlugin=python-ce
19 | sinceBuild=233.15325
20 | untilBuild=
21 | downloadIdeaSources=true
22 | publishUsername=leinardi
23 | publishChannels=Stable
24 | #######################################################################################################################
25 | # To run PyCharm from a custom path, uncomment and change the following line
26 | # pycharmPath=/home/leinardi/pycharm-community
27 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/leinardi/pylint-pycharm/0db20e71511920c98713b5156d99b2421549ac2c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Roberto Leinardi.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | rootProject.name = 'pylint-pycharm'
18 |
19 |
--------------------------------------------------------------------------------
/src/main/java/com/leinardi/pycharm/pylint/PylintBatchInspection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Roberto Leinardi.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.leinardi.pycharm.pylint;
18 |
19 | import com.intellij.codeInspection.LocalInspectionTool;
20 | import com.intellij.codeInspection.ex.ExternalAnnotatorBatchInspection;
21 | import org.jetbrains.annotations.NotNull;
22 |
23 | /**
24 | * By itself, the `PylintAnnotator` class does not provide support for the explicit "Inspect code" feature.
25 | *
26 | * This class uses `ExternalAnnotatorBatchInspection` middleware to provides that functionality.
27 | *
28 | * Modeled after `com.jetbrains.python.inspections.PyPep8Inspection`
29 | */
30 | public class PylintBatchInspection extends LocalInspectionTool implements ExternalAnnotatorBatchInspection {
31 | public static final String INSPECTION_SHORT_NAME = "Pylint";
32 |
33 | @Override
34 | public @NotNull String getShortName() {
35 | return INSPECTION_SHORT_NAME;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/leinardi/pycharm/pylint/PylintBundle.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Roberto Leinardi.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.leinardi.pycharm.pylint;
18 |
19 | import com.intellij.AbstractBundle;
20 | import org.jetbrains.annotations.NonNls;
21 | import org.jetbrains.annotations.PropertyKey;
22 |
23 | public final class PylintBundle extends AbstractBundle {
24 | @NonNls
25 | private static final String BUNDLE = "com.leinardi.pycharm.pylint.PylintBundle";
26 |
27 | private static final PylintBundle INSTANCE = new PylintBundle();
28 |
29 | private PylintBundle() {
30 | super(BUNDLE);
31 | }
32 |
33 | public static String message(@PropertyKey(resourceBundle = BUNDLE) final String key, final Object... params) {
34 | return INSTANCE.getMessage(key, params);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/leinardi/pycharm/pylint/PylintConfigService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Roberto Leinardi.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.leinardi.pycharm.pylint;
18 |
19 | import com.intellij.openapi.components.PersistentStateComponent;
20 | import com.intellij.openapi.components.State;
21 | import com.intellij.openapi.components.Storage;
22 | import com.intellij.openapi.project.Project;
23 | import com.intellij.util.xmlb.XmlSerializerUtil;
24 | import org.jetbrains.annotations.NotNull;
25 | import org.jetbrains.annotations.Nullable;
26 |
27 | @State(name = "PylintConfigService", storages = {@Storage("pylint.xml")})
28 | public class PylintConfigService implements PersistentStateComponent {
29 | public PylintConfigService() {
30 | customPylintPath = "";
31 | pylintArguments = "";
32 | pylintrcPath = "";
33 | scanBeforeCheckin = true;
34 | }
35 |
36 | private String customPylintPath;
37 | private String pylintrcPath;
38 | private String pylintArguments;
39 | private boolean scanBeforeCheckin;
40 |
41 | public String getCustomPylintPath() {
42 | return customPylintPath;
43 | }
44 |
45 | public void setCustomPylintPath(String pathToPylint) {
46 | this.customPylintPath = pathToPylint;
47 | }
48 |
49 | public String getPylintrcPath() {
50 | return pylintrcPath;
51 | }
52 |
53 | public void setPylintrcPath(String pathToPylintrcFile) {
54 | this.pylintrcPath = pathToPylintrcFile;
55 | }
56 |
57 | public String getPylintArguments() {
58 | return pylintArguments;
59 | }
60 |
61 | public void setPylintArguments(String pylintArguments) {
62 | this.pylintArguments = pylintArguments;
63 | }
64 |
65 | public boolean isScanBeforeCheckin() {
66 | return scanBeforeCheckin;
67 | }
68 |
69 | public void setScanBeforeCheckin(boolean scanBeforeCheckin) {
70 | this.scanBeforeCheckin = scanBeforeCheckin;
71 | }
72 |
73 | @Nullable
74 | @Override
75 | public PylintConfigService getState() {
76 | return this;
77 | }
78 |
79 | @Override
80 | public void loadState(@NotNull PylintConfigService config) {
81 | XmlSerializerUtil.copyBean(config, this);
82 | }
83 |
84 | @Nullable
85 | public static PylintConfigService getInstance(Project project) {
86 | return project.getService(PylintConfigService.class);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/com/leinardi/pycharm/pylint/PylintConfigurable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Roberto Leinardi.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.leinardi.pycharm.pylint;
18 |
19 | import com.intellij.openapi.diagnostic.Logger;
20 | import com.intellij.openapi.options.Configurable;
21 | import com.intellij.openapi.project.Project;
22 | import com.leinardi.pycharm.pylint.ui.PylintConfigPanel;
23 | import org.jetbrains.annotations.NotNull;
24 |
25 | import javax.swing.JComponent;
26 |
27 | /**
28 | * The "configurable component" required by PyCharm to provide a Swing form for inclusion into the 'Settings'
29 | * dialog. Registered in {@code plugin.xml} as a {@code projectConfigurable} extension.
30 | */
31 | public class PylintConfigurable implements Configurable {
32 | private static final Logger LOG = Logger.getInstance(PylintConfigurable.class);
33 |
34 | private final PylintConfigPanel configPanel;
35 | private final PylintConfigService pylintConfigService;
36 |
37 | public PylintConfigurable(@NotNull final Project project) {
38 | this(project, new PylintConfigPanel(project));
39 | }
40 |
41 | PylintConfigurable(@NotNull final Project project,
42 | @NotNull final PylintConfigPanel configPanel) {
43 | this.configPanel = configPanel;
44 | pylintConfigService = PylintConfigService.getInstance(project);
45 | }
46 |
47 | @Override
48 | public String getDisplayName() {
49 | return PylintBundle.message("plugin.configuration-name");
50 | }
51 |
52 | @Override
53 | public String getHelpTopic() {
54 | return null;
55 | }
56 |
57 | @Override
58 | public JComponent createComponent() {
59 | reset();
60 | return configPanel.getPanel();
61 | }
62 |
63 | @Override
64 | public void reset() {
65 | }
66 |
67 | @Override
68 | public boolean isModified() {
69 | boolean result = !configPanel.getPylintPath().equals(pylintConfigService.getCustomPylintPath())
70 | || !configPanel.getPylintrcPath().equals(pylintConfigService.getPylintrcPath())
71 | || !configPanel.getPylintArguments().equals(pylintConfigService.getPylintArguments());
72 | if (LOG.isDebugEnabled()) {
73 | LOG.debug("Has config changed? " + result);
74 | }
75 | return result;
76 | }
77 |
78 | @Override
79 | public void apply() {
80 | pylintConfigService.setCustomPylintPath(configPanel.getPylintPath());
81 | pylintConfigService.setPylintrcPath(configPanel.getPylintrcPath());
82 | pylintConfigService.setPylintArguments(configPanel.getPylintArguments());
83 | }
84 |
85 | @Override
86 | public void disposeUIResources() {
87 | // do nothing
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/leinardi/pycharm/pylint/PylintPlugin.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Roberto Leinardi.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.leinardi.pycharm.pylint;
18 |
19 | import com.intellij.openapi.components.Service;
20 | import com.intellij.openapi.diagnostic.Logger;
21 | import com.intellij.openapi.project.Project;
22 | import com.intellij.openapi.project.ProjectUtil;
23 | import com.intellij.openapi.vfs.VirtualFile;
24 | import com.intellij.psi.PsiFile;
25 | import com.leinardi.pycharm.pylint.checker.Problem;
26 | import com.leinardi.pycharm.pylint.checker.ScanFiles;
27 | import com.leinardi.pycharm.pylint.checker.ScannerListener;
28 | import com.leinardi.pycharm.pylint.checker.UiFeedbackScannerListener;
29 | import com.leinardi.pycharm.pylint.exception.PylintPluginException;
30 | import com.leinardi.pycharm.pylint.util.Async;
31 | import org.jetbrains.annotations.NotNull;
32 | import org.jetbrains.annotations.Nullable;
33 |
34 | import java.io.File;
35 | import java.util.Collections;
36 | import java.util.HashSet;
37 | import java.util.List;
38 | import java.util.Map;
39 | import java.util.Set;
40 | import java.util.concurrent.Future;
41 |
42 | import static com.leinardi.pycharm.pylint.util.Async.whenFinished;
43 |
44 | /**
45 | * Main class for the Pylint scanning plug-in.
46 | */
47 | @Service
48 | public final class PylintPlugin {
49 |
50 | private static final Logger LOG = com.intellij.openapi.diagnostic.Logger.getInstance(PylintPlugin.class);
51 |
52 | private static final long NO_TIMEOUT = 0L;
53 |
54 | private final Set> checksInProgress = new HashSet<>();
55 | private final Project project;
56 |
57 | /**
58 | * Construct a plug-in instance for the given project.
59 | *
60 | * @param project the current project.
61 | */
62 | public PylintPlugin(@NotNull final Project project) {
63 | this.project = project;
64 |
65 | LOG.info("Pylint Plugin loaded with project base dir: \"" + getProjectPath() + "\"");
66 |
67 | }
68 |
69 | public Project getProject() {
70 | return project;
71 | }
72 |
73 | @Nullable
74 | private File getProjectPath() {
75 | final VirtualFile baseDir = ProjectUtil.guessProjectDir(project);
76 | if (baseDir == null) {
77 | return null;
78 | }
79 |
80 | return new File(baseDir.getPath());
81 | }
82 |
83 | /**
84 | * Is a scan in progress?
85 | *