├── .dockerignore ├── .flake8 ├── .github ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── build.yml │ ├── build_base_image.yml │ ├── build_image.yml │ ├── publish.yml │ └── sort_whitespaces.yml ├── .gitignore ├── .intellij_inspector └── .idea │ ├── vcs.xml │ └── workspace.xml ├── .python-version ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── base.Dockerfile ├── hyperstyle ├── __init__.py └── src │ ├── __init__.py │ └── python │ ├── __init__.py │ ├── common │ ├── __init__.py │ └── tool_arguments.py │ └── review │ ├── __init__.py │ ├── application_config.py │ ├── common │ ├── __init__.py │ ├── file_system.py │ ├── java_compiler.py │ ├── language.py │ ├── language_version.py │ ├── parallel_runner.py │ └── subprocess_runner.py │ ├── inspectors │ ├── __init__.py │ ├── checkstyle │ │ ├── __init__.py │ │ ├── checkstyle.py │ │ ├── files │ │ │ └── config.xml │ │ ├── issue_configs.py │ │ └── issue_types.py │ ├── common │ │ ├── __init__.py │ │ ├── inspector │ │ │ ├── __init__.py │ │ │ ├── base_inspector.py │ │ │ ├── ij_client.py │ │ │ ├── inspector_type.py │ │ │ └── proto │ │ │ │ ├── __init__.py │ │ │ │ └── model.proto │ │ ├── issue │ │ │ ├── __init__.py │ │ │ ├── base_issue_converter.py │ │ │ ├── issue.py │ │ │ ├── issue_configs.py │ │ │ └── tips.py │ │ ├── utils.py │ │ └── xml_parser.py │ ├── detekt │ │ ├── __init__.py │ │ ├── detekt.py │ │ ├── files │ │ │ └── detekt-config.yml │ │ ├── issue_configs.py │ │ └── issue_types.py │ ├── eslint │ │ ├── .eslintrc │ │ ├── __init__.py │ │ ├── eslint.py │ │ ├── issue_configs.py │ │ └── issue_types.py │ ├── flake8 │ │ ├── .flake8 │ │ ├── __init__.py │ │ ├── flake8.py │ │ ├── issue_configs.py │ │ ├── issue_types.py │ │ └── whitelist.txt │ ├── golang_lint │ │ ├── __init__.py │ │ ├── config.yml │ │ ├── golang_lint.py │ │ ├── issue_configs.py │ │ └── issue_types.py │ ├── ij_java │ │ ├── __init__.py │ │ ├── ij_java.py │ │ ├── issue_configs.py │ │ └── issue_types.py │ ├── ij_kotlin │ │ ├── __init__.py │ │ ├── ij_kotlin.py │ │ ├── issue_configs.py │ │ └── issue_types.py │ ├── ij_python │ │ ├── __init__.py │ │ ├── ij_python.py │ │ ├── issue_configs.py │ │ └── issue_types.py │ ├── pmd │ │ ├── __init__.py │ │ ├── files │ │ │ └── config.xml │ │ ├── issue_configs.py │ │ ├── issue_types.py │ │ └── pmd.py │ ├── pyast │ │ ├── __init__.py │ │ └── python_ast.py │ ├── pylint │ │ ├── __init__.py │ │ ├── issue_configs.py │ │ ├── issue_types.py │ │ ├── pylint.py │ │ └── pylintrc │ └── radon │ │ ├── __init__.py │ │ └── radon.py │ ├── logging_config.py │ ├── quality │ ├── __init__.py │ ├── evaluate_quality.py │ ├── model.py │ ├── penalty.py │ └── rules │ │ ├── __init__.py │ │ ├── best_practices_scoring.py │ │ ├── boolean_length_scoring.py │ │ ├── class_response_scoring.py │ │ ├── code_style_scoring.py │ │ ├── cohesion_scoring.py │ │ ├── complexity_scoring.py │ │ ├── coupling_scoring.py │ │ ├── cyclomatic_complexity_scoring.py │ │ ├── error_prone_scoring.py │ │ ├── function_length_scoring.py │ │ ├── inheritance_depth_scoring.py │ │ ├── line_len_scoring.py │ │ ├── maintainability_scoring.py │ │ ├── method_number_scoring.py │ │ └── weighted_methods_scoring.py │ ├── reviewers │ ├── __init__.py │ ├── common.py │ ├── exceptions.py │ ├── go.py │ ├── perform_review.py │ ├── python.py │ ├── review_result.py │ └── utils │ │ ├── __init__.py │ │ ├── code_statistics.py │ │ ├── issues_filter.py │ │ ├── metadata_exploration.py │ │ └── print_review.py │ └── run_tool.py ├── package.json ├── poetry.lock ├── pyproject.toml ├── setup_environment.sh ├── test ├── __init__.py ├── python │ ├── __init__.py │ ├── functional_tests │ │ ├── __init__.py │ │ ├── conftest.py │ │ ├── test_different_languages.py │ │ ├── test_difficulty_levels.py │ │ ├── test_disable.py │ │ ├── test_duplicates.py │ │ ├── test_exit_code.py │ │ ├── test_file_or_project.py │ │ ├── test_json_format.py │ │ ├── test_range_of_lines.py │ │ └── test_verbosity.py │ ├── inspectors │ │ ├── __init__.py │ │ ├── conftest.py │ │ ├── test_checkstyle_inspector.py │ │ ├── test_common.py │ │ ├── test_detekt_inspector.py │ │ ├── test_eslint_inspector.py │ │ ├── test_filter_duplicate_issues.py │ │ ├── test_flake8_inspector.py │ │ ├── test_golang_lint_inspector.py │ │ ├── test_issue_configs.py │ │ ├── test_local_review.py │ │ ├── test_out_of_range_issues.py │ │ ├── test_pmd_inspector.py │ │ ├── test_pylint_inspector.py │ │ ├── test_python_ast.py │ │ └── test_radon_inspector.py │ └── quality │ │ ├── __init__.py │ │ └── test_penalty.py └── resources │ ├── functional_tests │ ├── different_languages │ │ ├── go │ │ │ ├── a.go │ │ │ ├── b.go │ │ │ └── go.mod │ │ ├── java │ │ │ └── src │ │ │ │ ├── First.java │ │ │ │ └── Second.java │ │ ├── kotlin │ │ │ ├── main.kt │ │ │ └── person.kt │ │ └── python │ │ │ ├── a.py │ │ │ └── b.py │ ├── difficulty_levels │ │ ├── file_with_all_difficulty_levels.py │ │ ├── file_with_only_easy_issues.py │ │ ├── file_with_only_hard_issues.py │ │ ├── file_with_only_medium_issues.py │ │ └── file_without_issues.py │ ├── disable │ │ └── contains_flake8_issues.py │ ├── duplicates │ │ └── code_with_duplicate_issues.py │ ├── exit_codes │ │ ├── no_issues.py │ │ └── with_issues.py │ ├── file_or_project │ │ ├── file.py │ │ ├── project │ │ │ ├── __init__.py │ │ │ ├── one.py │ │ │ └── other.py │ │ └── project_with_unknown_extensions │ │ │ ├── file.abc │ │ │ ├── file.py │ │ │ └── file.xyz │ ├── lines_range │ │ └── code_with_multiple_issues.py │ └── verbosity │ │ └── some_code.py │ └── inspectors │ ├── checkstyle │ ├── empty_file.xml │ ├── issues │ │ ├── BooleanExpressionComplexityCheck.java │ │ ├── CyclomaticComplexityCheck.java │ │ ├── JavaNCSSCheck.java │ │ ├── LineLengthCheck.java │ │ └── MagicNumberCheck.java │ ├── multi_file_project_with_metric_issues.xml │ ├── multi_file_project_without_issues.xml │ ├── multi_file_project_without_metric_issues.xml │ ├── single_file_project_with_metric_issues.xml │ ├── single_file_project_without_issues.xml │ └── single_file_project_without_metric_issues.xml │ ├── detekt │ └── issues │ │ ├── ComplexCondition.kt │ │ ├── ComplexMethod.kt │ │ ├── LongMethod.kt │ │ └── MagicNumber.kt │ ├── eslint │ └── issues │ │ └── complexity.js │ ├── flake8 │ └── issues │ │ ├── b007.py │ │ ├── c901.py │ │ ├── e501.py │ │ ├── h601.py │ │ ├── wps350.py │ │ └── wps432.py │ ├── go │ ├── case0_empty.go │ ├── case10_gocritic_issues.go │ ├── case11_gosimple_issues.go │ ├── case12_stylecheck_issues.go │ ├── case13_staticcheck_issues.go │ ├── case14_whitespace.go │ ├── case15_deadcode.go │ ├── case16_errcheck.go │ ├── case17_magic_numbers.go │ ├── case18_generics.go │ ├── case1_simple_valid_program.go │ ├── case2_program_with_syntax_errors.go │ ├── case3_issues_with_related_information.go │ ├── case4_cyclomatic_complexity.go │ ├── case5_function_length.go │ ├── case6_line_length.go │ ├── case7_maintainability.go │ ├── case8_govet_issues.go │ └── case9_revive_issues.go │ ├── golang_lint │ ├── empty_file.json │ ├── issues │ │ ├── cyclop.go │ │ ├── funlen.go │ │ ├── gomnd.go │ │ ├── lll.go │ │ └── maintidx.go │ ├── multi_file_project_with_issues.json │ ├── multi_file_project_without_issues.json │ ├── single_file_project_with_issues.json │ └── single_file_project_without_issues.json │ ├── intellij_output │ └── test.xml │ ├── java │ ├── test_algorithm_with_scanner.java │ ├── test_array_type.java │ ├── test_blocks.java │ ├── test_boolean_expr.java │ ├── test_builder.java │ ├── test_class_with_booleans.java │ ├── test_closing_streams.java │ ├── test_code_with_comments.java │ ├── test_comparing_strings.java │ ├── test_constants.java │ ├── test_covariant_equals.java │ ├── test_curly_braces.java │ ├── test_cyclomatic_complexity.java │ ├── test_cyclomatic_complexity_bad.java │ ├── test_double_checked_locking.java │ ├── test_empty_line_separator.java │ ├── test_empty_lines_btw_members.java │ ├── test_for_loop.java │ ├── test_implementation_types.java │ ├── test_indentation_google_style.java │ ├── test_indentation_with_spaces.java │ ├── test_indentation_with_tabs.java │ ├── test_invalid_naming.java │ ├── test_long_lines.java │ ├── test_magic_numbers.java │ ├── test_manual_array_copy.java │ ├── test_method_params.java │ ├── test_missing_default.java │ ├── test_multi_statements.java │ ├── test_multiple_literals.java │ ├── test_nested_blocks.java │ ├── test_pattern_matching.java │ ├── test_reassigning_example.java │ ├── test_records.java │ ├── test_sealed_classes.java │ ├── test_simple_valid_program.java │ ├── test_spaces.java │ ├── test_suppress_rules.java │ ├── test_switch_statement.java │ ├── test_ternary_operator.java │ ├── test_thread_run.java │ ├── test_todo.java │ ├── test_too_long_method.java │ ├── test_unused_imports.java │ ├── test_upper_ell.java │ ├── test_valid_algorithm_1.java │ ├── test_valid_blocks.java │ ├── test_valid_curly_braces.java │ ├── test_valid_default.java │ ├── test_valid_naming.java │ ├── test_valid_spaces.java │ └── test_when_only_equals_overridden.java │ ├── js │ ├── case0_no_issues.js │ ├── case1_with_issues.js │ └── case2_semi_node_and_unused.js │ ├── kotlin │ ├── case0_good_program.kt │ ├── case10_long_lines.kt │ ├── case11_bad_ident.kt │ ├── case12_bad_filename.kt │ ├── case13_good_filename.kt │ ├── case14_keyword_spacing.kt │ ├── case15_empty_class_func.kt │ ├── case16_redundant_unit.kt │ ├── case17_modifier_order.kt │ ├── case18_redundant_braces.kt │ ├── case19_private_property.kt │ ├── case1_coffee_machine.kt │ ├── case20_cyclomatic_complexity.kt │ ├── case21_cyclomatic_complexity_bad.kt │ ├── case22_too_many_arguments.kt │ ├── case23_bad_range_performance.kt │ ├── case24_duplicate_when_bug.kt │ ├── case25_unreachable_code.kt │ ├── case26_var_could_be_val.kt │ ├── case2_valid_program.kt │ ├── case3_todo.kt │ ├── case4_semicolons.kt │ ├── case5_imports.kt │ ├── case6_missing_spaces.kt │ ├── case7_immutability.kt │ ├── case8_needless_blank_line.kt │ └── case9_braces.kt │ ├── pmd │ ├── empty_file.csv │ ├── multi_file_project.csv │ ├── project_without_issues.csv │ └── single_file_project.csv │ ├── pylint │ └── issues │ │ ├── r1721.py │ │ └── w1404.py │ ├── python │ ├── case0_folder_without_init │ │ └── hello.py │ ├── case0_spaces.py │ ├── case10_unused_variable_in_loop.py │ ├── case11_redundant_parentheses.py │ ├── case12_unreachable_code.py │ ├── case13_complex_logic.py │ ├── case13_complex_logic_2.py │ ├── case14_returns_errors.py │ ├── case15_redefining.py │ ├── case16_comments.py │ ├── case17_dangerous_default_value.py │ ├── case18_comprehensions.py │ ├── case19_bad_indentation.py │ ├── case1_simple_valid_program.py │ ├── case20_imports_order.py │ ├── case21_imports.py │ ├── case22_reassigning.py │ ├── case23_merging_comparisons.py │ ├── case24_long_function.py │ ├── case25_django.py │ ├── case26_from_stepik.py │ ├── case27_using_requests.py │ ├── case28_todo_list.py │ ├── case29_whitespaces.py │ ├── case2_boolean_expressions.py │ ├── case30_allow_else_return.py │ ├── case31_line_break.py │ ├── case31_spellcheck.py │ ├── case32_string_format.py │ ├── case33_commas.py │ ├── case34_cohesion.py │ ├── case35_line_break.py │ ├── case36_unpacking.py │ ├── case37_wildcard_import.py │ ├── case38_spellcheck.py │ ├── case39_no_issues.py │ ├── case3_redefining_builtin.py │ ├── case4_naming.py │ ├── case5_returns.py │ ├── case6_unused_variables.py │ ├── case7_empty_lines.py │ ├── case8_good_class.py │ └── case_duplicates.py │ ├── python_ast │ ├── function.py │ ├── many_bool_expressions.py │ └── one_bool_expression.py │ └── spring │ ├── case1 │ └── test_promiscuous_controller.java │ ├── case2 │ └── test_class_with_booleans.java │ └── springlint-result-example.html ├── tox.ini └── whitelist.txt /.dockerignore: -------------------------------------------------------------------------------- 1 | **/*.pyc 2 | **/.pytest_cache/ 3 | **/__pycache__/ 4 | .git 5 | .github 6 | .idea 7 | node_modules 8 | venv 9 | .venv 10 | build 11 | **/*.egg-info 12 | **/model_pb2* 13 | linters 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | target-branch: main 6 | schedule: 7 | interval: "daily" 8 | time: "00:00" 9 | groups: 10 | all-actions: 11 | patterns: [ "*" ] 12 | 13 | - package-ecosystem: "pip" 14 | directory: "/" 15 | target-branch: main 16 | schedule: 17 | interval: "daily" 18 | time: "00:00" 19 | open-pull-requests-limit: 1 20 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | **Issues**: 2 | [Issue#](https://github.com/hyperskill/hyperstyle/issues/#) 3 | 4 | **Description**: 5 | 6 | -------------------------------------------------------------------------------- /.github/workflows/build_base_image.yml: -------------------------------------------------------------------------------- 1 | name: Build Base Image 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | image_tag: 7 | type: string 8 | description: 'Image tag' 9 | required: true 10 | default: 'py3.10.14-java11.0.11-node14.17.3-go1.18.5' 11 | 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.ref }} 14 | cancel-in-progress: false 15 | 16 | jobs: 17 | build_base_image: 18 | name: Build Base Image 19 | runs-on: [ self-hosted, small ] 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - uses: docker/login-action@v3 24 | with: 25 | registry: hyperskill.azurecr.io 26 | username: ${{ secrets.REGISTRY_USER }} 27 | password: ${{ secrets.REGISTRY_PASSWORD }} 28 | 29 | - uses: docker/setup-buildx-action@v3 30 | 31 | - name: Build and push server image 32 | uses: docker/build-push-action@v6 33 | with: 34 | platforms: linux/amd64 35 | context: . 36 | pull: true 37 | push: true 38 | file: base.Dockerfile 39 | tags: hyperskill.azurecr.io/hyperstyle-base:${{ inputs.image_tag }} 40 | cache-from: | 41 | type=gha 42 | type=gha,scope=main 43 | cache-to: type=gha,mode=max 44 | -------------------------------------------------------------------------------- /.github/workflows/build_image.yml: -------------------------------------------------------------------------------- 1 | name: Build Image after Release 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | image_tag: 7 | description: 'Image tag' 8 | required: true 9 | default: 'latest' 10 | release: 11 | types: 12 | - released 13 | 14 | concurrency: 15 | group: ${{ github.workflow }}-${{ github.ref }} 16 | cancel-in-progress: false 17 | 18 | jobs: 19 | build_image: 20 | name: Build Image 21 | runs-on: [ self-hosted, small ] 22 | steps: 23 | - uses: actions/checkout@v4 24 | 25 | - uses: docker/login-action@v3 26 | with: 27 | registry: hyperskill.azurecr.io 28 | username: ${{ secrets.REGISTRY_USER }} 29 | password: ${{ secrets.REGISTRY_PASSWORD }} 30 | 31 | - uses: docker/setup-buildx-action@v3 32 | 33 | - name: Build and push server image 34 | uses: docker/build-push-action@v6 35 | with: 36 | context: . 37 | pull: true 38 | push: true 39 | tags: hyperskill.azurecr.io/hyperstyle:${{ inputs.image_tag || github.event.release.tag_name }} 40 | cache-from: | 41 | type=gha 42 | type=gha,scope=main 43 | cache-to: type=gha,mode=max 44 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to PyPI in case of releasing 2 | 3 | on: 4 | push: 5 | 6 | concurrency: 7 | group: ${{ github.workflow }}-${{ github.ref }} 8 | cancel-in-progress: false 9 | 10 | jobs: 11 | build-n-publish: 12 | name: Build and publish Python 🐍 distributions 📦 to PyPI 13 | runs-on: [ self-hosted, small ] 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | - name: Set up Python 18 | uses: actions/setup-python@v5 19 | with: 20 | python-version-file: .python-version 21 | - name: Install pypa/build 22 | run: | 23 | python -m pip install build --user 24 | - name: Build a binary wheel and a source tarball 25 | run: | 26 | python -m build --sdist --wheel --outdir dist/ . 27 | - name: Publish distribution 📦 to PyPI 28 | if: startsWith(github.ref, 'refs/tags') 29 | uses: pypa/gh-action-pypi-publish@master 30 | with: 31 | password: ${{ secrets.SECRETS_TEST_PYPI_API_TOKEN }} 32 | -------------------------------------------------------------------------------- /.github/workflows/sort_whitespaces.yml: -------------------------------------------------------------------------------- 1 | name: Sort whitespaces 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - develop 8 | paths: 9 | - 'whitelist.txt' 10 | - 'hyperstyle/src/python/review/inspectors/flake8/whitelist.txt' 11 | pull_request: 12 | paths: 13 | - 'whitelist.txt' 14 | - 'hyperstyle/src/python/review/inspectors/flake8/whitelist.txt' 15 | 16 | concurrency: 17 | group: ${{ github.workflow }}-${{ github.ref }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | sort_whitespaces: 22 | name: Sort whitespaces 23 | runs-on: [ self-hosted, small ] 24 | steps: 25 | - name: Checkout 26 | uses: actions/checkout@v4 27 | 28 | - name: Sort whitelists 29 | run: | 30 | for file in "whitelist.txt" "hyperstyle/src/python/review/inspectors/flake8/whitelist.txt" 31 | do 32 | LC_ALL=C sort $file -o $file 33 | done 34 | 35 | - name: Commit sorted whitelists 36 | uses: EndBug/add-and-commit@v9.1.4 37 | with: 38 | add: "['whitelist.txt', 'hyperstyle/src/python/review/inspectors/flake8/whitelist.txt']" 39 | message: 'Sort whitelists (Github Actions)' 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | *.Python 12 | *env/ 13 | *build/ 14 | *develop-eggs/ 15 | *dist/ 16 | *downloads/ 17 | *eggs/ 18 | *.eggs/ 19 | *lib64/ 20 | *parts/ 21 | *sdist/ 22 | *var/ 23 | *.egg-info/ 24 | *.installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | *pip-log.txt 35 | *pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | *htmlcov/ 39 | *.tox/ 40 | *.coverage 41 | *.coverage.* 42 | *.cache 43 | *nosetests.xml 44 | *coverage.xml 45 | *,cover 46 | 47 | # Translations 48 | *.mo 49 | *.pot 50 | 51 | # Django stuff: 52 | *.log 53 | 54 | # Sphinx documentation 55 | *docs/_build/ 56 | 57 | # PyBuilder 58 | *target/ 59 | 60 | # Zip files 61 | *.zip 62 | 63 | *.pickle 64 | *.ipynb_checkpoints/ 65 | 66 | *.gz 67 | 68 | *.tmp 69 | *.pmd 70 | *.checkstyle 71 | *.intellij_formatter 72 | *.all/ 73 | 74 | /.idea/ 75 | /.intellij/ 76 | /.intellij_inspector/src/* 77 | /.intellij_inspector/out/ 78 | 79 | lightweight.Dockerfile 80 | linters 81 | 82 | node_modules 83 | .eslintrc.js 84 | package-lock.json 85 | 86 | hyperstyle/src/python/review/inspectors/common/inspector/proto/model_pb2* 87 | .env 88 | -------------------------------------------------------------------------------- /.intellij_inspector/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.intellij_inspector/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 1577277297642 21 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.10.14 2 | -------------------------------------------------------------------------------- /hyperstyle/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pathlib import Path 4 | 5 | MAIN_FOLDER = Path(__file__) 6 | -------------------------------------------------------------------------------- /hyperstyle/src/python/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/common/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/application_config.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from dataclasses import dataclass 4 | from typing import TYPE_CHECKING 5 | 6 | if TYPE_CHECKING: 7 | from hyperstyle.src.python.review.common.language import Language 8 | from hyperstyle.src.python.review.inspectors.common.inspector.inspector_type import InspectorType 9 | 10 | 11 | @dataclass 12 | class ApplicationConfig: 13 | disabled_inspectors: set[InspectorType] 14 | allow_duplicates: bool 15 | n_cpu: int 16 | inspectors_config: dict 17 | with_all_categories: bool 18 | start_line: int = 1 19 | language: Language | None = None 20 | end_line: int | None = None 21 | new_format: bool = False 22 | history: str | None = None 23 | group_by_difficulty: bool = False 24 | ij_config: str | None = None 25 | 26 | @staticmethod 27 | def get_default_config() -> ApplicationConfig: 28 | return ApplicationConfig( 29 | disabled_inspectors=set(), 30 | allow_duplicates=False, 31 | n_cpu=1, 32 | inspectors_config={"n_cpu": 1}, 33 | with_all_categories=True, 34 | start_line=1, 35 | language=None, 36 | new_format=False, 37 | group_by_difficulty=False, 38 | ) 39 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/common/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/common/java_compiler.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import logging 4 | import subprocess 5 | from typing import TYPE_CHECKING 6 | 7 | from hyperstyle.src.python.review.common.file_system import Encoding, Extension 8 | 9 | if TYPE_CHECKING: 10 | from pathlib import Path 11 | 12 | logger = logging.getLogger(__name__) 13 | 14 | 15 | # TODO: it cannot compile gradle-based projects 16 | def javac_project(dir_path: Path) -> bool: 17 | return javac(f'$(find {dir_path} -name "*{Extension.JAVA.value}")') 18 | 19 | 20 | def javac(javac_args: str | Path) -> bool: 21 | try: 22 | output_bytes: bytes = subprocess.check_output( 23 | f"javac {javac_args}", 24 | shell=True, 25 | stderr=subprocess.STDOUT, 26 | ) 27 | output_str = str(output_bytes, Encoding.UTF_ENCODING.value) 28 | 29 | if output_str: 30 | logger.debug(output_str) 31 | except subprocess.CalledProcessError as error: 32 | logger.exception( 33 | f"Failed compile java code with error: " f"{str(error.stdout, Encoding.UTF_ENCODING.value)}" 34 | ) 35 | return False 36 | else: 37 | return True 38 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/common/language.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum, unique 4 | from typing import TYPE_CHECKING 5 | 6 | from hyperstyle.src.python.review.common.file_system import Extension 7 | from hyperstyle.src.python.review.common.language_version import LanguageVersion 8 | 9 | if TYPE_CHECKING: 10 | from pathlib import Path 11 | 12 | 13 | @unique 14 | class Language(Enum): 15 | JAVA = "JAVA" 16 | PYTHON = "PYTHON" 17 | KOTLIN = "KOTLIN" 18 | JS = "JAVASCRIPT" 19 | GO = "GO" 20 | UNKNOWN = "UNKNOWN" 21 | 22 | @staticmethod 23 | def from_language_version(language_version: LanguageVersion) -> Language: 24 | version_to_lang = { 25 | LanguageVersion.JAVA_7: Language.JAVA, 26 | LanguageVersion.JAVA_8: Language.JAVA, 27 | LanguageVersion.JAVA_9: Language.JAVA, 28 | LanguageVersion.JAVA_11: Language.JAVA, 29 | LanguageVersion.JAVA_15: Language.JAVA, 30 | LanguageVersion.JAVA_17: Language.JAVA, 31 | LanguageVersion.PYTHON_3: Language.PYTHON, 32 | LanguageVersion.KOTLIN: Language.KOTLIN, 33 | LanguageVersion.JS: Language.JS, 34 | LanguageVersion.GO: Language.GO, 35 | } 36 | 37 | return version_to_lang.get(language_version, Language.UNKNOWN) 38 | 39 | @classmethod 40 | def values(cls) -> list[str]: 41 | return [member.value for member in Language] 42 | 43 | @classmethod 44 | def from_value(cls, value: str, default: Language | None = None) -> Language | None: 45 | try: 46 | return Language(value) 47 | except ValueError: 48 | return default 49 | 50 | 51 | EXTENSION_TO_LANGUAGE = { 52 | Extension.JAVA: Language.JAVA, 53 | Extension.PY: Language.PYTHON, 54 | Extension.KT: Language.KOTLIN, 55 | Extension.KTS: Language.KOTLIN, 56 | Extension.JS: Language.JS, 57 | Extension.GO: Language.GO, 58 | } 59 | 60 | 61 | def guess_file_language(file_path: Path) -> Language: 62 | extension = Extension.from_file(file_path) 63 | 64 | if extension is None: 65 | return Language.UNKNOWN 66 | 67 | return EXTENSION_TO_LANGUAGE.get(extension, Language.UNKNOWN) 68 | 69 | 70 | def filter_paths_by_language(file_paths: list[Path], language: Language) -> list[Path]: 71 | result = [] 72 | for path in file_paths: 73 | if guess_file_language(path) == language: 74 | result.append(path) 75 | return result 76 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/common/language_version.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum, unique 4 | 5 | from hyperstyle.src.python.review.common.file_system import Extension 6 | 7 | 8 | @unique 9 | class LanguageVersion(Enum): 10 | JAVA_7 = "java7" 11 | JAVA_8 = "java8" 12 | JAVA_9 = "java9" 13 | JAVA_11 = "java11" 14 | JAVA_15 = "java15" 15 | JAVA_17 = "java17" 16 | PYTHON_3 = "python3" 17 | KOTLIN = "kotlin" 18 | JS = "javascript" 19 | GO = "go" 20 | 21 | @classmethod 22 | def values(cls) -> list[str]: 23 | return [member.value for member in cls.__members__.values()] 24 | 25 | @classmethod 26 | def language_to_extension_dict(cls) -> dict[LanguageVersion, Extension]: 27 | return { 28 | cls.JAVA_7: Extension.JAVA, 29 | cls.JAVA_8: Extension.JAVA, 30 | cls.JAVA_9: Extension.JAVA, 31 | cls.JAVA_11: Extension.JAVA, 32 | cls.JAVA_15: Extension.JAVA, 33 | cls.JAVA_17: Extension.JAVA, 34 | cls.PYTHON_3: Extension.PY, 35 | cls.KOTLIN: Extension.KT, 36 | cls.JS: Extension.JS, 37 | cls.GO: Extension.GO, 38 | } 39 | 40 | def extension_by_language(self) -> Extension: 41 | return self.language_to_extension_dict()[self] 42 | 43 | def is_java(self) -> bool: 44 | return self in { 45 | LanguageVersion.JAVA_7, 46 | LanguageVersion.JAVA_8, 47 | LanguageVersion.JAVA_9, 48 | LanguageVersion.JAVA_11, 49 | LanguageVersion.JAVA_15, 50 | LanguageVersion.JAVA_17, 51 | } 52 | 53 | @classmethod 54 | def from_value(cls, value: str, default: LanguageVersion | None = None) -> LanguageVersion | None: 55 | try: 56 | return LanguageVersion(value) 57 | except ValueError: 58 | return default 59 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/common/parallel_runner.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import functools 4 | import itertools 5 | import logging 6 | import multiprocessing 7 | from typing import Any, TYPE_CHECKING 8 | 9 | if TYPE_CHECKING: 10 | from collections.abc import Callable 11 | from pathlib import Path 12 | 13 | from hyperstyle.src.python.review.application_config import ApplicationConfig 14 | from hyperstyle.src.python.review.inspectors.common.inspector.base_inspector import BaseInspector 15 | from hyperstyle.src.python.review.inspectors.common.issue.issue import BaseIssue 16 | 17 | logger = logging.getLogger(__name__) 18 | 19 | 20 | def run_inspector(path: Path, config: ApplicationConfig, inspector: BaseInspector) -> list[BaseIssue]: 21 | return _run_inspector(inspector.inspect, path, config, inspector) 22 | 23 | 24 | def run_inspector_in_memory( 25 | code: str, config: ApplicationConfig, inspector: BaseInspector 26 | ) -> list[BaseIssue]: 27 | return _run_inspector(inspector.inspect_in_memory, code, config, inspector) 28 | 29 | 30 | def _run_inspector( 31 | inspect_function: Callable[[Any, dict[str, Any]], list[BaseIssue]], 32 | data: Any, 33 | config: ApplicationConfig, 34 | inspector: BaseInspector, 35 | ) -> list[BaseIssue]: 36 | try: 37 | return inspect_function(data, config.inspectors_config) 38 | except Exception: 39 | logger.exception(f"Inspector {inspector.inspector_type} failed.") 40 | raise 41 | 42 | 43 | def inspect_in_parallel( 44 | inspector_runner: Callable[[Any, ApplicationConfig, BaseInspector], list[BaseIssue]], 45 | data: Any, 46 | config: ApplicationConfig, 47 | inspectors: list[BaseInspector], 48 | ) -> list[BaseIssue]: 49 | inspectors_to_run = filter(lambda i: i.inspector_type not in config.disabled_inspectors, inspectors) 50 | 51 | if config.n_cpu == 1: 52 | issues = [] 53 | for inspector in inspectors_to_run: 54 | inspector_issues = inspector_runner(data, config, inspector) 55 | issues.extend(inspector_issues) 56 | return issues 57 | 58 | with multiprocessing.Pool(config.n_cpu) as pool: 59 | issues = pool.map( 60 | functools.partial(inspector_runner, data, config), 61 | inspectors_to_run, 62 | ) 63 | 64 | return list(itertools.chain(*issues)) 65 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/common/subprocess_runner.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import logging 4 | import subprocess 5 | from typing import TYPE_CHECKING 6 | 7 | if TYPE_CHECKING: 8 | from pathlib import Path 9 | 10 | logger = logging.getLogger(__name__) 11 | 12 | 13 | def run_in_subprocess( 14 | command: list[str], 15 | working_directory: str | Path | None = None, 16 | encoding: str = "utf-8", 17 | subprocess_input: str | None = None, 18 | ) -> str: 19 | process = subprocess.run( 20 | command, 21 | capture_output=True, 22 | cwd=working_directory, 23 | encoding=encoding, 24 | input=subprocess_input, 25 | check=False, 26 | ) 27 | 28 | stdout = process.stdout 29 | stderr = process.stderr 30 | 31 | if stdout: 32 | logger.debug(f"{command[0]}'s stdout:\n{stdout}") 33 | if stderr: 34 | logger.debug(f"{command[0]}'s stderr:\n{stderr}") 35 | 36 | return stdout 37 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/checkstyle/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/checkstyle/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/checkstyle/issue_configs.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import re 4 | 5 | from hyperstyle.src.python.review.inspectors.common.issue.issue_configs import ( 6 | IssueConfig, 7 | IssueDescriptionParser, 8 | MeasurableIssueConfig, 9 | ) 10 | from hyperstyle.src.python.review.inspectors.common.issue.tips import ( 11 | get_bool_expr_len_tip, 12 | get_cyclomatic_complexity_tip, 13 | get_func_len_tip, 14 | get_line_len_tip, 15 | get_magic_number_tip, 16 | ) 17 | 18 | ISSUE_CONFIGS: list[IssueConfig] = [ 19 | IssueConfig( 20 | origin_class="MagicNumberCheck", 21 | new_description=get_magic_number_tip(), 22 | parser=IssueDescriptionParser(re.compile(r"'(.+)' is a magic number")), 23 | ), 24 | # Cyclomatic complexity 25 | MeasurableIssueConfig( 26 | origin_class="CyclomaticComplexityCheck", 27 | new_description=get_cyclomatic_complexity_tip(), 28 | parser=IssueDescriptionParser( 29 | regexp=re.compile(r"Cyclomatic Complexity is (\d+)"), 30 | converter={0: int}, 31 | ), 32 | ), 33 | # Function length 34 | MeasurableIssueConfig( 35 | origin_class="JavaNCSSCheck", 36 | new_description=get_func_len_tip(), 37 | parser=IssueDescriptionParser( 38 | regexp=re.compile(r"NCSS for this method is (\d+)"), 39 | converter={0: int}, 40 | ), 41 | ), 42 | # Bool expression length 43 | MeasurableIssueConfig( 44 | origin_class="BooleanExpressionComplexityCheck", 45 | new_description=get_bool_expr_len_tip(), 46 | parser=IssueDescriptionParser( 47 | regexp=re.compile(r"Boolean expression complexity is (\d+)"), 48 | converter={0: int}, 49 | ), 50 | ), 51 | # Line length 52 | MeasurableIssueConfig( 53 | origin_class="LineLengthCheck", 54 | new_description=get_line_len_tip(), 55 | parser=IssueDescriptionParser( 56 | regexp=re.compile(r"Line is longer than \d+ characters \(found (\d+)\)"), 57 | converter={0: int}, 58 | ), 59 | ), 60 | ] 61 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/common/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/common/inspector/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/common/inspector/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/common/inspector/ij_client.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import grpc 4 | 5 | from hyperstyle.src.python.review.inspectors.common.inspector.proto import model_pb2, model_pb2_grpc 6 | 7 | TIMEOUT = 3 8 | 9 | 10 | class IJClient: 11 | def __init__(self, host: str = "localhost", port: int = 8080) -> None: 12 | self.host = host 13 | self.port = port 14 | 15 | # instantiate a channel 16 | self.channel = grpc.insecure_channel(f"{self.host}:{self.port}") 17 | 18 | # bind the client and the server 19 | try: 20 | grpc.channel_ready_future(self.channel).result(timeout=TIMEOUT) 21 | except grpc.FutureTimeoutError as e: 22 | msg = "Failed to connect to ij code server" 23 | raise Exception(msg) from e 24 | else: 25 | self.stub = model_pb2_grpc.CodeInspectionServiceStub(self.channel) 26 | 27 | def inspect(self, code: model_pb2.Code) -> model_pb2.InspectionResult: 28 | return self.stub.inspect(code, timeout=TIMEOUT) 29 | 30 | def init(self, service: model_pb2.Service) -> model_pb2.InitResult: 31 | return self.stub.init(service, timeout=TIMEOUT) 32 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/common/inspector/inspector_type.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from enum import Enum, unique 4 | 5 | 6 | @unique 7 | class InspectorType(Enum): 8 | # Python language 9 | PYLINT = "PYLINT" 10 | PYTHON_AST = "PYTHON_AST" 11 | FLAKE8 = "FLAKE8" 12 | RADON = "RADON" 13 | IJ_PYTHON = "IJ_PYTHON" 14 | 15 | # Java language 16 | PMD = "PMD" 17 | CHECKSTYLE = "CHECKSTYLE" 18 | IJ_JAVA = "IJ_JAVA" 19 | 20 | # Kotlin language 21 | DETEKT = "DETEKT" 22 | IJ_KOTLIN = "IJ_KOTLIN" 23 | 24 | # JavaScript language 25 | ESLINT = "ESLINT" 26 | 27 | # Go language 28 | GOLANG_LINT = "GOLANG_LINT" 29 | 30 | UNDEFINED = "UNDEFINED" 31 | QODANA = "QODANA" 32 | # TODO: it is used on production for java inspections, remove in the future releases 33 | IJ_OLD = "INTELLIJ" 34 | 35 | @classmethod 36 | def available_values(cls) -> list[str]: 37 | return [ 38 | # Python language 39 | cls.PYLINT.value, 40 | cls.FLAKE8.value, 41 | cls.PYTHON_AST.value, 42 | cls.RADON.value, 43 | cls.IJ_PYTHON.value, 44 | # Java language 45 | cls.PMD.value, 46 | cls.CHECKSTYLE.value, 47 | cls.IJ_JAVA.value, 48 | # Kotlin language 49 | cls.DETEKT.value, 50 | cls.IJ_KOTLIN.value, 51 | # JavaScript language 52 | cls.ESLINT.value, 53 | # Go language 54 | cls.GOLANG_LINT.value, 55 | cls.IJ_OLD.value, 56 | ] 57 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/common/inspector/proto/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/common/inspector/proto/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/common/inspector/proto/model.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_multiple_files = true; 4 | option java_package = "org.jetbrains.research.ij.headless.server"; 5 | option java_outer_classname = "CodeServerProto"; 6 | 7 | service CodeInspectionService { 8 | rpc inspect (Code) returns (InspectionResult) {}; 9 | } 10 | 11 | enum LanguageId { 12 | python = 0; 13 | kotlin = 1; 14 | java = 2; 15 | } 16 | 17 | message Code { 18 | string text = 1; 19 | LanguageId languageId = 2; 20 | } 21 | 22 | message Problem { 23 | string name = 1; 24 | string inspector = 2; 25 | uint64 lineNumber = 3; 26 | uint64 offset = 4; 27 | uint64 length = 5; 28 | } 29 | 30 | message InspectionResult { 31 | repeated Problem problems = 1; 32 | } 33 | 34 | message Service { 35 | string name = 1; 36 | LanguageId languageId = 2; 37 | } 38 | 39 | message InitResult { 40 | uint64 status = 1; 41 | } 42 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/common/issue/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/common/issue/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/common/issue/base_issue_converter.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import logging 4 | from typing import TYPE_CHECKING 5 | 6 | from hyperstyle.src.python.review.inspectors.common.issue.issue import ( 7 | BaseIssue, 8 | get_issue_class_by_issue_type, 9 | get_measure_name_by_measurable_issue_type, 10 | IssueData, 11 | Measurable, 12 | ) 13 | 14 | if TYPE_CHECKING: 15 | from hyperstyle.src.python.review.inspectors.common.issue.issue_configs import IssueConfigsHandler 16 | 17 | logger = logging.getLogger(__name__) 18 | 19 | 20 | def convert_base_issue(base_issue: BaseIssue, issue_configs_handler: IssueConfigsHandler) -> BaseIssue | None: 21 | """Convert the ``base_issue`` to a code issue or measurable one. 22 | 23 | If necessary, the old description is replaced by the new one and the measure is parsed using the 24 | ``issue_configs_handler``. 25 | 26 | :param base_issue: A base issue to be converted. 27 | :param issue_configs_handler: A handler of issue configurations. 28 | :return: 29 | """ 30 | origin_class = base_issue.origin_class 31 | issue_type = base_issue.type 32 | description = base_issue.description 33 | inspector_type = base_issue.inspector_type 34 | 35 | issue_data = vars(base_issue) # Get all the fields from BaseIssue, so we can change them 36 | issue_data[IssueData.DESCRIPTION.value] = issue_configs_handler.get_description(origin_class, description) 37 | 38 | issue_class = get_issue_class_by_issue_type(issue_type) 39 | if issubclass(issue_class, Measurable): 40 | measure = issue_configs_handler.parse_measure(origin_class, description) 41 | if measure is None: 42 | logger.error(f"{inspector_type.value}: Unable to parse measure.") 43 | return None 44 | 45 | issue_data[get_measure_name_by_measurable_issue_type(issue_type)] = measure 46 | 47 | try: 48 | return issue_class(**issue_data) 49 | except Exception: 50 | logger.exception(f"{inspector_type.value}: Unable to create a new issue.") 51 | return None 52 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/common/utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import logging 4 | from math import floor 5 | from string import Formatter 6 | from typing import TYPE_CHECKING 7 | 8 | from hyperstyle.src.python.review.common.file_system import get_content_from_file 9 | 10 | if TYPE_CHECKING: 11 | from pathlib import Path 12 | 13 | from hyperstyle.src.python.review.inspectors.common.inspector.inspector_type import InspectorType 14 | 15 | logger = logging.getLogger(__name__) 16 | 17 | 18 | def is_result_file_correct(file_path: Path, inspector_type: InspectorType) -> bool: 19 | """Check if the result of the inspectors is correct: it exists and it is not empty.""" 20 | if not file_path.is_file(): 21 | logger.error(f"{inspector_type.value}: error - no output file") 22 | return False 23 | 24 | file_content = get_content_from_file(file_path) 25 | if not file_content: 26 | logger.error(f"{inspector_type.value}: error - empty file") 27 | return False 28 | 29 | return True 30 | 31 | 32 | def convert_percentage_of_value_to_lack_of_value(percentage_of_value: float) -> int: 33 | """Converts percentage of value to lack of value. 34 | Calculated by the formula: floor(100 - percentage_of_value). 35 | 36 | :param percentage_of_value: value in the range from 0 to 100. 37 | :return: lack of value. 38 | """ 39 | return floor(100 - percentage_of_value) 40 | 41 | 42 | def _get_format_fields(input_string: str) -> list[str]: 43 | """Get all format fields from the input string. 44 | 45 | :param input_string: A string from which all format fields need to be extracted. 46 | :return: A list of format fields. 47 | """ 48 | return [elem[1] for elem in Formatter().parse(input_string) if elem[1] is not None] 49 | 50 | 51 | def contains_format_fields(input_string: str) -> bool: 52 | """Check that the input string contains format fields. 53 | 54 | :param input_string: A string for which you want to check whether it contains format fields or not. 55 | :return: Whether the input string contains format fields or not. 56 | """ 57 | return len(_get_format_fields(input_string)) > 0 58 | 59 | 60 | def contains_named_format_fields(input_string: str) -> bool: 61 | """Check that the input string contains named format fields. 62 | 63 | :param input_string: A string for which you want to check whether it contains named format fields or not. 64 | :return: Whether the input string contains named format fields or not. 65 | """ 66 | return any(field and not field.isdigit() for field in _get_format_fields(input_string)) 67 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/detekt/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/detekt/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/detekt/issue_configs.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import re 4 | 5 | from hyperstyle.src.python.review.inspectors.common.issue.issue_configs import ( 6 | IssueConfig, 7 | IssueDescriptionParser, 8 | MeasurableIssueConfig, 9 | ) 10 | from hyperstyle.src.python.review.inspectors.common.issue.tips import ( 11 | get_bool_expr_len_tip, 12 | get_cyclomatic_complexity_tip, 13 | get_func_len_tip, 14 | get_magic_number_tip, 15 | ) 16 | 17 | ISSUE_CONFIGS: list[IssueConfig] = [ 18 | IssueConfig( 19 | origin_class="MagicNumber", 20 | new_description=get_magic_number_tip(with_number_field=False), 21 | ), 22 | # Function length 23 | MeasurableIssueConfig( 24 | origin_class="LongMethod", 25 | new_description=get_func_len_tip(), 26 | parser=IssueDescriptionParser( 27 | regexp=re.compile(r"The function .* is too long \((\d+)\)"), 28 | converter={0: int}, 29 | ), 30 | ), 31 | # Bool expression length 32 | MeasurableIssueConfig( 33 | origin_class="ComplexCondition", 34 | new_description=get_bool_expr_len_tip(unit_name="operands"), 35 | parser=IssueDescriptionParser( 36 | regexp=re.compile(r"This condition is too complex \((\d+)\)"), 37 | converter={0: int}, 38 | ), 39 | ), 40 | # Cyclomatic complexity 41 | MeasurableIssueConfig( 42 | origin_class="ComplexMethod", 43 | new_description=get_cyclomatic_complexity_tip(), 44 | parser=IssueDescriptionParser( 45 | regexp=re.compile(r"The function .* appears to be too complex \((\d+)\)"), 46 | converter={0: int}, 47 | ), 48 | ), 49 | ] 50 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/eslint/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 2020, 4 | "sourceType": "script", 5 | "ecmaFeatures": {} 6 | }, 7 | "extends": "eslint:recommended", 8 | "rules": { 9 | "no-misleading-character-class": "off", 10 | "no-setter-return": "off", 11 | "no-unsafe-negation": "off", 12 | "no-unsafe-finally": "off", 13 | "no-undef": "off", 14 | "no-console": "off", 15 | 16 | "complexity": ["error", 5], 17 | "curly": "error", 18 | "consistent-return": "error", 19 | "default-case": "error", 20 | "eqeqeq": "error", 21 | "no-empty-function": "error", 22 | "no-fallthrough": "error", 23 | "no-multi-spaces": "error", 24 | "yoda": "error", 25 | 26 | "brace-style": "error", 27 | "camelcase": "error", 28 | "comma-style": "error", 29 | "comma-spacing": "error", 30 | "semi": "error", 31 | "no-multiple-empty-lines": "error", 32 | "no-var": "error", 33 | "space-infix-ops": "error", 34 | "object-curly-newline" : "error", 35 | "no-trailing-spaces": "error", 36 | "no-whitespace-before-property": "error", 37 | "max-len": ["error", { "code": 80 }], 38 | "constructor-super": "error" 39 | }, 40 | "env": {} 41 | } 42 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/eslint/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/eslint/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/eslint/issue_configs.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import re 4 | 5 | from hyperstyle.src.python.review.inspectors.common.issue.issue_configs import ( 6 | IssueConfig, 7 | IssueDescriptionParser, 8 | MeasurableIssueConfig, 9 | ) 10 | from hyperstyle.src.python.review.inspectors.common.issue.tips import get_cyclomatic_complexity_tip 11 | 12 | ISSUE_CONFIGS: list[IssueConfig] = [ 13 | MeasurableIssueConfig( 14 | origin_class="complexity", 15 | new_description=get_cyclomatic_complexity_tip(), 16 | parser=IssueDescriptionParser( 17 | regexp=re.compile(r"complexity of (\d+)"), 18 | converter={0: int}, 19 | ), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/flake8/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/flake8/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/flake8/issue_configs.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import re 4 | 5 | from hyperstyle.src.python.review.inspectors.common.issue.issue_configs import ( 6 | IssueConfig, 7 | IssueDescriptionParser, 8 | MeasurableIssueConfig, 9 | ) 10 | from hyperstyle.src.python.review.inspectors.common.issue.tips import ( 11 | get_augmented_assign_pattern_tip, 12 | get_cohesion_tip, 13 | get_cyclomatic_complexity_tip, 14 | get_line_len_tip, 15 | get_magic_number_tip, 16 | ) 17 | from hyperstyle.src.python.review.inspectors.common.utils import convert_percentage_of_value_to_lack_of_value 18 | 19 | ISSUE_CONFIGS: list[IssueConfig] = [ 20 | IssueConfig( 21 | origin_class="WPS432", 22 | new_description=get_magic_number_tip(), 23 | parser=IssueDescriptionParser(re.compile(r"^Found magic number: (.+)$")), 24 | ), 25 | IssueConfig( 26 | origin_class="WPS350", 27 | new_description=get_augmented_assign_pattern_tip(), 28 | ), 29 | IssueConfig( 30 | origin_class="B007", 31 | new_description=( 32 | "Loop control variable '{0}' not used within the loop body. " 33 | "If this is intended, replace it with an underscore." 34 | ), 35 | parser=IssueDescriptionParser( 36 | re.compile(r"Loop control variable '(.+)' not used within the loop body") 37 | ), 38 | ), 39 | # Cyclomatic Complexity 40 | MeasurableIssueConfig( 41 | origin_class="C901", 42 | new_description=get_cyclomatic_complexity_tip(), 43 | parser=IssueDescriptionParser( 44 | regexp=re.compile(r"'.+' is too complex \((\d+)\)"), 45 | converter={0: int}, 46 | ), 47 | ), 48 | # Cohesion 49 | MeasurableIssueConfig( 50 | origin_class="H601", 51 | new_description=get_cohesion_tip(), 52 | parser=IssueDescriptionParser( 53 | regexp=re.compile(r"class has low \((\d*\.?\d*)%\) cohesion"), 54 | converter={0: lambda match: convert_percentage_of_value_to_lack_of_value(float(match))}, 55 | ), 56 | ), 57 | # Line len 58 | MeasurableIssueConfig( 59 | origin_class="E501", 60 | new_description=get_line_len_tip(), 61 | parser=IssueDescriptionParser( 62 | regexp=re.compile(r"line too long \((\d+) > \d+ characters\)"), 63 | converter={0: int}, 64 | ), 65 | ), 66 | ] 67 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/flake8/whitelist.txt: -------------------------------------------------------------------------------- 1 | acc 2 | aggfunc 3 | appendleft 4 | arange 5 | argmax 6 | asctime 7 | astype 8 | barmode 9 | betavariate 10 | bgcolor 11 | birthdate 12 | blackbox 13 | bs4 14 | byteorder 15 | calc 16 | capwords 17 | casefold 18 | caseless 19 | chappie 20 | concat 21 | config 22 | configs 23 | consts 24 | coord 25 | copysign 26 | coroutine 27 | csgraph 28 | ctime 29 | dataframe 30 | dataframes 31 | dataset 32 | datasets 33 | decrypted 34 | dedent 35 | deque 36 | desc 37 | destructuring 38 | devs 39 | df 40 | dicts 41 | dirs 42 | divmod 43 | dtype 44 | edu 45 | eig 46 | elems 47 | etree 48 | expm1 49 | falsy 50 | fillna 51 | floordiv 52 | fromkeys 53 | fromstring 54 | fullmatch 55 | gensim 56 | getchildren 57 | gmtime 58 | groupby 59 | gryffindor 60 | halfs 61 | hashable 62 | hline 63 | href 64 | hufflepuff 65 | hyp 66 | hyperskill 67 | iadd 68 | iloc 69 | inp 70 | inplace 71 | ints 72 | isalnum 73 | isalpha 74 | isin 75 | islice 76 | islower 77 | isnumeric 78 | isprintable 79 | istitle 80 | isub 81 | iterrows 82 | kcal 83 | kcals 84 | lastname 85 | lateinit 86 | lemmatize 87 | lemmatizer 88 | lifes 89 | lightbulb 90 | lim 91 | linalg 92 | linecolor 93 | linewidth 94 | linspace 95 | lowercased 96 | lvl 97 | lxml 98 | matmul 99 | metaclass 100 | minsize 101 | multiline 102 | nbins 103 | ndarray 104 | ndigits 105 | ndim 106 | nltk 107 | nrows 108 | nullable 109 | numpy 110 | nums 111 | ost 112 | param 113 | params 114 | parsers 115 | pathlib 116 | popleft 117 | pos 118 | punct 119 | ravenclaw 120 | readline 121 | rfind 122 | rindex 123 | rmdir 124 | schur 125 | scipy 126 | showline 127 | sigmoid 128 | slytherin 129 | sqrt 130 | src 131 | stdlib 132 | stemmer 133 | stepik 134 | subdicts 135 | subdir 136 | subdirs 137 | substr 138 | substring 139 | svd 140 | textposition 141 | textwrap 142 | throwable 143 | todos 144 | tokenize 145 | tokenized 146 | tokenizer 147 | tolist 148 | toplevel 149 | tracklist 150 | treebank 151 | truediv 152 | truthy 153 | unary 154 | uniformtext 155 | unpickled 156 | upd 157 | util 158 | utils 159 | vline 160 | webpage 161 | whitespaces 162 | word2vec 163 | writeback 164 | xanchor 165 | xaxes 166 | yanchor 167 | yaxis 168 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/golang_lint/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/golang_lint/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/golang_lint/issue_configs.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import re 4 | 5 | from hyperstyle.src.python.review.inspectors.common.issue.issue_configs import ( 6 | IssueConfig, 7 | IssueDescriptionParser, 8 | MeasurableIssueConfig, 9 | ) 10 | from hyperstyle.src.python.review.inspectors.common.issue.tips import ( 11 | get_cyclomatic_complexity_tip, 12 | get_func_len_tip, 13 | get_line_len_tip, 14 | get_magic_number_tip, 15 | get_maintainability_index_tip, 16 | ) 17 | from hyperstyle.src.python.review.inspectors.common.utils import convert_percentage_of_value_to_lack_of_value 18 | 19 | ISSUE_CONFIGS: list[IssueConfig] = [ 20 | IssueConfig( 21 | origin_class="gomnd", 22 | new_description=get_magic_number_tip(), 23 | parser=IssueDescriptionParser(re.compile("^mnd: Magic number: (.*), in .* detected$")), 24 | ), 25 | MeasurableIssueConfig( 26 | origin_class="cyclop", 27 | new_description=get_cyclomatic_complexity_tip(), 28 | parser=IssueDescriptionParser( 29 | regexp=re.compile(r"^calculated cyclomatic complexity for function .* is (\d+), max is -1$"), 30 | converter={0: int}, 31 | ), 32 | ), 33 | MeasurableIssueConfig( 34 | origin_class="funlen", 35 | new_description=get_func_len_tip(), 36 | parser=IssueDescriptionParser( 37 | regexp=re.compile(r"^Function '.*' is too long \((\d+) > 1\)$"), 38 | converter={0: int}, 39 | ), 40 | ), 41 | MeasurableIssueConfig( 42 | origin_class="lll", 43 | new_description=get_line_len_tip(), 44 | parser=IssueDescriptionParser( 45 | regexp=re.compile(r"^line is (\d+) characters$"), 46 | converter={0: int}, 47 | ), 48 | ), 49 | MeasurableIssueConfig( 50 | origin_class="maintidx", 51 | new_description=get_maintainability_index_tip(), 52 | parser=IssueDescriptionParser( 53 | regexp=re.compile( 54 | r"^Function name: .*, Cyclomatic Complexity: .*, Halstead Volume: .*, Maintainability Index: (.+)$", 55 | ), 56 | converter={0: lambda group: convert_percentage_of_value_to_lack_of_value(float(group))}, 57 | ), 58 | ), 59 | ] 60 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/ij_java/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/ij_java/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/ij_java/ij_java.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from hyperstyle.src.python.review.inspectors.common.inspector.base_inspector import BaseIJInspector 4 | from hyperstyle.src.python.review.inspectors.common.inspector.inspector_type import InspectorType 5 | from hyperstyle.src.python.review.inspectors.common.inspector.proto import model_pb2 6 | from hyperstyle.src.python.review.inspectors.ij_java.issue_configs import ISSUE_CONFIGS 7 | from hyperstyle.src.python.review.inspectors.ij_java.issue_types import ( 8 | IJ_INSPECTION_TO_ISSUE_TYPE, 9 | IJ_MESSAGE_TO_ISSUE_TYPE, 10 | ) 11 | 12 | 13 | class JavaIJInspector(BaseIJInspector): 14 | inspector_type = InspectorType.IJ_JAVA 15 | language_id = model_pb2.LanguageId.java 16 | issue_configs = ISSUE_CONFIGS 17 | ij_inspection_to_issue_type = IJ_INSPECTION_TO_ISSUE_TYPE 18 | ij_message_to_issue_type = IJ_MESSAGE_TO_ISSUE_TYPE 19 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/ij_java/issue_configs.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import TYPE_CHECKING 4 | 5 | if TYPE_CHECKING: 6 | from hyperstyle.src.python.review.inspectors.common.issue.issue_configs import IssueConfig 7 | 8 | ISSUE_CONFIGS: list[IssueConfig] = [] 9 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/ij_java/issue_types.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | IJ_INSPECTION_TO_ISSUE_TYPE = {} 4 | 5 | IJ_MESSAGE_TO_ISSUE_TYPE = {} 6 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/ij_kotlin/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/ij_kotlin/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/ij_kotlin/ij_kotlin.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from hyperstyle.src.python.review.inspectors.common.inspector.base_inspector import BaseIJInspector 4 | from hyperstyle.src.python.review.inspectors.common.inspector.inspector_type import InspectorType 5 | from hyperstyle.src.python.review.inspectors.common.inspector.proto import model_pb2 6 | from hyperstyle.src.python.review.inspectors.ij_kotlin.issue_configs import ISSUE_CONFIGS 7 | from hyperstyle.src.python.review.inspectors.ij_kotlin.issue_types import ( 8 | IJ_INSPECTION_TO_ISSUE_TYPE, 9 | IJ_MESSAGE_TO_ISSUE_TYPE, 10 | ) 11 | 12 | 13 | class KotlinIJInspector(BaseIJInspector): 14 | inspector_type = InspectorType.IJ_KOTLIN 15 | language_id = model_pb2.LanguageId.kotlin 16 | issue_configs = ISSUE_CONFIGS 17 | ij_inspection_to_issue_type = IJ_INSPECTION_TO_ISSUE_TYPE 18 | ij_message_to_issue_type = IJ_MESSAGE_TO_ISSUE_TYPE 19 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/ij_kotlin/issue_configs.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import TYPE_CHECKING 4 | 5 | if TYPE_CHECKING: 6 | from hyperstyle.src.python.review.inspectors.common.issue.issue_configs import IssueConfig 7 | 8 | ISSUE_CONFIGS: list[IssueConfig] = [] 9 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/ij_kotlin/issue_types.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | IJ_INSPECTION_TO_ISSUE_TYPE = {} 4 | 5 | IJ_MESSAGE_TO_ISSUE_TYPE = {} 6 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/ij_python/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/ij_python/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/ij_python/ij_python.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from hyperstyle.src.python.review.inspectors.common.inspector.base_inspector import BaseIJInspector 4 | from hyperstyle.src.python.review.inspectors.common.inspector.inspector_type import InspectorType 5 | from hyperstyle.src.python.review.inspectors.common.inspector.proto import model_pb2 6 | from hyperstyle.src.python.review.inspectors.ij_python.issue_configs import ISSUE_CONFIGS 7 | from hyperstyle.src.python.review.inspectors.ij_python.issue_types import ( 8 | IJ_INSPECTION_TO_ISSUE_TYPE, 9 | IJ_MESSAGE_TO_ISSUE_TYPE, 10 | ) 11 | 12 | 13 | class PythonIJInspector(BaseIJInspector): 14 | inspector_type = InspectorType.IJ_PYTHON 15 | language_id = model_pb2.LanguageId.python 16 | issue_configs = ISSUE_CONFIGS 17 | ij_inspection_to_issue_type = IJ_INSPECTION_TO_ISSUE_TYPE 18 | ij_message_to_issue_type = IJ_MESSAGE_TO_ISSUE_TYPE 19 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/ij_python/issue_configs.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from hyperstyle.src.python.review.inspectors.common.issue.issue_configs import IssueConfig 4 | 5 | ISSUE_CONFIGS: list[IssueConfig] = [ 6 | IssueConfig( 7 | origin_class="E128", 8 | new_description="Incorrect indent", 9 | ), 10 | ] 11 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/pmd/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/pmd/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/pmd/issue_configs.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import TYPE_CHECKING 4 | 5 | if TYPE_CHECKING: 6 | from hyperstyle.src.python.review.inspectors.common.issue.issue_configs import IssueConfig 7 | 8 | ISSUE_CONFIGS: list[IssueConfig] = [] 9 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/pyast/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/pyast/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/pylint/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/pylint/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/pylint/issue_configs.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from hyperstyle.src.python.review.inspectors.common.issue.issue_configs import IssueConfig 4 | 5 | ISSUE_CONFIGS: list[IssueConfig] = [ 6 | IssueConfig( 7 | origin_class="W1404", 8 | new_description='Found implicit string concatenation. If you want to concatenate strings, use "+".', 9 | ), 10 | IssueConfig( 11 | origin_class="R1721", 12 | new_description=( 13 | "Unnecessary use of a comprehension. Instead of using an identity comprehension, " 14 | "consider using the list, dict or set constructor. It is faster and simpler. " 15 | "For example, instead of {{key: value for key, value in list_of_tuples}} use dict(list_of_tuples)." 16 | ), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/inspectors/radon/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/inspectors/radon/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/logging_config.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import sys 4 | 5 | logging_config: dict[str, object] = { 6 | "version": 1, 7 | "formatters": { 8 | "common": { 9 | "class": "logging.Formatter", 10 | "format": "%(asctime)s | %(levelname)s | %(message)s", 11 | }, 12 | }, 13 | "handlers": { 14 | "console": { 15 | "class": "logging.StreamHandler", 16 | "level": "DEBUG", 17 | "formatter": "common", 18 | "stream": sys.stdout, 19 | }, 20 | }, 21 | "loggers": { 22 | "": { 23 | "handlers": ["console"], 24 | "level": "INFO", 25 | }, 26 | }, 27 | "disable_existing_loggers": False, 28 | } 29 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/quality/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/quality/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/quality/rules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/quality/rules/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/quality/rules/class_response_scoring.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from dataclasses import dataclass 4 | 5 | from hyperstyle.src.python.review.common.language import Language 6 | from hyperstyle.src.python.review.inspectors.common.issue.issue import IssueType 7 | from hyperstyle.src.python.review.quality.model import QualityType, Rule 8 | 9 | 10 | @dataclass 11 | class ResponseRuleConfig: 12 | response_moderate: int 13 | response_good: int 14 | 15 | 16 | common_response_rule_config = ResponseRuleConfig( 17 | response_moderate=69, 18 | response_good=59, 19 | ) 20 | 21 | LANGUAGE_TO_RESPONSE_RULE_CONFIG = { 22 | Language.JAVA: common_response_rule_config, 23 | Language.PYTHON: common_response_rule_config, 24 | Language.KOTLIN: common_response_rule_config, 25 | Language.JS: common_response_rule_config, 26 | Language.GO: common_response_rule_config, 27 | } 28 | 29 | 30 | class ResponseRule(Rule): 31 | def __init__(self, config: ResponseRuleConfig) -> None: 32 | self.config = config 33 | self.rule_type = IssueType.CLASS_RESPONSE 34 | self.response: int | None = None 35 | 36 | def apply(self, response: int) -> None: 37 | self.response = response 38 | if response > self.config.response_moderate: 39 | self.quality_type = QualityType.MODERATE 40 | self.next_level_delta = response - self.config.response_moderate 41 | elif response > self.config.response_good: 42 | self.quality_type = QualityType.GOOD 43 | self.next_level_delta = response - self.config.response_good 44 | else: 45 | self.quality_type = QualityType.EXCELLENT 46 | self.next_level_delta = response 47 | self.next_level_type = self.__get_next_quality_type() 48 | 49 | def __get_next_quality_type(self) -> QualityType: 50 | if self.quality_type == QualityType.MODERATE: 51 | return QualityType.GOOD 52 | return QualityType.EXCELLENT 53 | 54 | def merge(self, other: ResponseRule) -> ResponseRule: 55 | config = ResponseRuleConfig( 56 | min(self.config.response_moderate, other.config.response_moderate), 57 | min(self.config.response_good, other.config.response_good), 58 | ) 59 | result_rule = ResponseRule(config) 60 | result_rule.apply(max(self.response, other.response)) 61 | 62 | return result_rule 63 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/quality/rules/coupling_scoring.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from dataclasses import dataclass 4 | 5 | from hyperstyle.src.python.review.common.language import Language 6 | from hyperstyle.src.python.review.inspectors.common.issue.issue import IssueType 7 | from hyperstyle.src.python.review.quality.model import QualityType, Rule 8 | 9 | 10 | @dataclass 11 | class CouplingRuleConfig: 12 | coupling_bad: int 13 | coupling_moderate: int 14 | 15 | 16 | common_coupling_rule_config = CouplingRuleConfig( 17 | coupling_bad=30, 18 | coupling_moderate=20, 19 | ) 20 | 21 | LANGUAGE_TO_COUPLING_RULE_CONFIG = { 22 | Language.JAVA: common_coupling_rule_config, 23 | Language.PYTHON: common_coupling_rule_config, 24 | Language.KOTLIN: common_coupling_rule_config, 25 | Language.JS: common_coupling_rule_config, 26 | Language.GO: common_coupling_rule_config, 27 | } 28 | 29 | 30 | class CouplingRule(Rule): 31 | def __init__(self, config: CouplingRuleConfig) -> None: 32 | self.config = config 33 | self.rule_type = IssueType.COUPLING 34 | self.coupling: int | None = None 35 | 36 | def apply(self, coupling: int) -> None: 37 | self.coupling = coupling 38 | if coupling > self.config.coupling_bad: 39 | self.quality_type = QualityType.BAD 40 | self.next_level_delta = coupling - self.config.coupling_bad 41 | elif coupling > self.config.coupling_moderate: 42 | self.quality_type = QualityType.MODERATE 43 | self.next_level_delta = coupling - self.config.coupling_moderate 44 | else: 45 | self.quality_type = QualityType.EXCELLENT 46 | self.next_level_delta = coupling 47 | self.next_level_type = self.__get_next_quality_type() 48 | 49 | def __get_next_quality_type(self) -> QualityType: 50 | if self.quality_type == QualityType.BAD: 51 | return QualityType.MODERATE 52 | return QualityType.EXCELLENT 53 | 54 | def merge(self, other: CouplingRule) -> CouplingRule: 55 | config = CouplingRuleConfig( 56 | min(self.config.coupling_bad, other.config.coupling_bad), 57 | min(self.config.coupling_moderate, other.config.coupling_moderate), 58 | ) 59 | result_rule = CouplingRule(config) 60 | result_rule.apply(max(self.coupling, other.coupling)) 61 | 62 | return result_rule 63 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/quality/rules/error_prone_scoring.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from dataclasses import dataclass 4 | 5 | from hyperstyle.src.python.review.common.language import Language 6 | from hyperstyle.src.python.review.inspectors.common.issue.issue import IssueType 7 | from hyperstyle.src.python.review.quality.model import QualityType, Rule 8 | 9 | 10 | @dataclass 11 | class ErrorProneRuleConfig: 12 | n_error_prone_bad: int 13 | 14 | 15 | # TODO: It is necessary to add subcategories where the following boundaries can be used: 16 | # GOOD: 0 17 | # MODERATE: 1 18 | # BAD: 2 19 | common_error_prone_rule_config = ErrorProneRuleConfig( 20 | n_error_prone_bad=0, 21 | ) 22 | 23 | LANGUAGE_TO_ERROR_PRONE_RULE_CONFIG = { 24 | Language.JAVA: common_error_prone_rule_config, 25 | Language.KOTLIN: common_error_prone_rule_config, 26 | Language.PYTHON: common_error_prone_rule_config, 27 | Language.JS: common_error_prone_rule_config, 28 | Language.GO: common_error_prone_rule_config, 29 | } 30 | 31 | 32 | class ErrorProneRule(Rule): 33 | def __init__(self, config: ErrorProneRuleConfig) -> None: 34 | self.config = config 35 | self.rule_type = IssueType.ERROR_PRONE 36 | self.n_error_prone: int | None = None 37 | 38 | def apply(self, n_error_prone: int) -> None: 39 | self.n_error_prone = n_error_prone 40 | if n_error_prone > self.config.n_error_prone_bad: 41 | self.quality_type = QualityType.BAD 42 | self.next_level_delta = n_error_prone - self.config.n_error_prone_bad 43 | else: 44 | self.quality_type = QualityType.EXCELLENT 45 | self.next_level_delta = n_error_prone 46 | self.next_level_type = self.__get_next_quality_type() 47 | 48 | def __get_next_quality_type(self) -> QualityType: 49 | return QualityType.EXCELLENT 50 | 51 | def merge(self, other: ErrorProneRule) -> ErrorProneRule: 52 | config = ErrorProneRuleConfig(min(self.config.n_error_prone_bad, other.config.n_error_prone_bad)) 53 | result_rule = ErrorProneRule(config) 54 | result_rule.apply(self.n_error_prone + other.n_error_prone) 55 | 56 | return result_rule 57 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/quality/rules/function_length_scoring.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from dataclasses import dataclass 4 | 5 | from hyperstyle.src.python.review.common.language import Language 6 | from hyperstyle.src.python.review.inspectors.common.issue.issue import IssueType 7 | from hyperstyle.src.python.review.quality.model import QualityType, Rule 8 | 9 | 10 | @dataclass 11 | class FunctionLengthRuleConfig: 12 | func_len_bad: int 13 | 14 | 15 | LANGUAGE_TO_FUNCTION_LENGTH_RULE_CONFIG = { 16 | Language.JAVA: FunctionLengthRuleConfig( 17 | func_len_bad=69, 18 | ), 19 | Language.KOTLIN: FunctionLengthRuleConfig( 20 | func_len_bad=69, 21 | ), 22 | Language.PYTHON: FunctionLengthRuleConfig( 23 | func_len_bad=49, 24 | ), 25 | Language.JS: FunctionLengthRuleConfig( 26 | func_len_bad=69, 27 | ), 28 | # Using java config 29 | Language.GO: FunctionLengthRuleConfig( 30 | func_len_bad=69, 31 | ), 32 | } 33 | 34 | 35 | class FunctionLengthRule(Rule): 36 | def __init__(self, config: FunctionLengthRuleConfig) -> None: 37 | self.config = config 38 | self.rule_type = IssueType.FUNC_LEN 39 | self.func_len: int | None = None 40 | 41 | def apply(self, func_len: int) -> None: 42 | self.func_len = func_len 43 | if func_len > self.config.func_len_bad: 44 | self.quality_type = QualityType.BAD 45 | self.next_level_delta = func_len - self.config.func_len_bad 46 | else: 47 | self.quality_type = QualityType.EXCELLENT 48 | self.next_level_delta = 0 49 | self.next_level_type = self.__get_next_quality_type() 50 | 51 | def __get_next_quality_type(self) -> QualityType: 52 | return QualityType.EXCELLENT 53 | 54 | def merge(self, other: FunctionLengthRule) -> FunctionLengthRule: 55 | config = FunctionLengthRuleConfig( 56 | min(self.config.func_len_bad, other.config.func_len_bad), 57 | ) 58 | result_rule = FunctionLengthRule(config) 59 | result_rule.apply(max(self.func_len, other.func_len)) 60 | 61 | return result_rule 62 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/quality/rules/inheritance_depth_scoring.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from dataclasses import dataclass 4 | 5 | from hyperstyle.src.python.review.common.language import Language 6 | from hyperstyle.src.python.review.inspectors.common.issue.issue import IssueType 7 | from hyperstyle.src.python.review.quality.model import QualityType, Rule 8 | 9 | 10 | @dataclass 11 | class InheritanceDepthRuleConfig: 12 | depth_bad: int 13 | 14 | 15 | common_inheritance_depth_rule_config = InheritanceDepthRuleConfig( 16 | depth_bad=3, 17 | ) 18 | 19 | LANGUAGE_TO_INHERITANCE_DEPTH_RULE_CONFIG = { 20 | Language.JAVA: common_inheritance_depth_rule_config, 21 | Language.PYTHON: common_inheritance_depth_rule_config, 22 | Language.KOTLIN: common_inheritance_depth_rule_config, 23 | Language.JS: common_inheritance_depth_rule_config, 24 | Language.GO: common_inheritance_depth_rule_config, 25 | } 26 | 27 | 28 | class InheritanceDepthRule(Rule): 29 | def __init__(self, config: InheritanceDepthRuleConfig) -> None: 30 | self.config = config 31 | self.rule_type = IssueType.INHERITANCE_DEPTH 32 | self.depth: int | None = None 33 | 34 | def apply(self, depth: int) -> None: 35 | self.depth = depth 36 | if depth > self.config.depth_bad: 37 | self.quality_type = QualityType.BAD 38 | self.next_level_delta = depth - self.config.depth_bad 39 | else: 40 | self.quality_type = QualityType.EXCELLENT 41 | self.next_level_delta = depth 42 | self.next_level_type = self.__get_next_quality_type() 43 | 44 | def __get_next_quality_type(self) -> QualityType: 45 | return QualityType.EXCELLENT 46 | 47 | def merge(self, other: InheritanceDepthRule) -> InheritanceDepthRule: 48 | config = InheritanceDepthRuleConfig(min(self.config.depth_bad, other.config.depth_bad)) 49 | result_rule = InheritanceDepthRule(config) 50 | result_rule.apply(max(self.depth, other.depth)) 51 | 52 | return result_rule 53 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/reviewers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/reviewers/__init__.py -------------------------------------------------------------------------------- /hyperstyle/src/python/review/reviewers/exceptions.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | 4 | class UnsupportedLanguageError(Exception): 5 | pass 6 | 7 | 8 | class InspectionError(Exception): 9 | pass 10 | 11 | 12 | class PathNotExistsError(Exception): 13 | pass 14 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/reviewers/go.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import TYPE_CHECKING 4 | 5 | from hyperstyle.src.python.review.common.language import Language 6 | from hyperstyle.src.python.review.reviewers.common import perform_language_review 7 | from hyperstyle.src.python.review.reviewers.utils.metadata_exploration import Metadata, ProjectMetadata 8 | 9 | if TYPE_CHECKING: 10 | from hyperstyle.src.python.review.application_config import ApplicationConfig 11 | from hyperstyle.src.python.review.reviewers.review_result import GeneralReviewResult 12 | 13 | 14 | def perform_go_review(metadata: Metadata, config: ApplicationConfig) -> GeneralReviewResult: 15 | # The project must contain a go.mod file. If it's missing, then create it. 16 | if isinstance(metadata, ProjectMetadata): 17 | mod_file_path = metadata.path / "go.mod" 18 | if not mod_file_path.exists(): 19 | mod_file_path.write_text("module main") 20 | 21 | return perform_language_review(metadata, config, Language.GO) 22 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/reviewers/python.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import TYPE_CHECKING 4 | 5 | from hyperstyle.src.python.review.common.file_system import FileSystemItem, get_all_file_system_items 6 | from hyperstyle.src.python.review.common.language import Language 7 | from hyperstyle.src.python.review.reviewers.common import perform_language_review 8 | from hyperstyle.src.python.review.reviewers.utils.metadata_exploration import Metadata, ProjectMetadata 9 | 10 | if TYPE_CHECKING: 11 | from pathlib import Path 12 | 13 | from hyperstyle.src.python.review.application_config import ApplicationConfig 14 | from hyperstyle.src.python.review.reviewers.review_result import GeneralReviewResult 15 | 16 | 17 | def perform_python_review(metadata: Metadata, config: ApplicationConfig) -> GeneralReviewResult: 18 | created_file_paths = [] 19 | if isinstance(metadata, ProjectMetadata): 20 | created_file_paths.extend(create_init_scripts_in_subdirs(metadata.path)) 21 | 22 | review_result = perform_language_review(metadata, config, Language.PYTHON) 23 | review_result.file_review_results = [ 24 | file_review_result 25 | for file_review_result in review_result.file_review_results 26 | if file_review_result.file_path not in created_file_paths 27 | ] 28 | return review_result 29 | 30 | 31 | def create_init_scripts_in_subdirs(path: Path) -> list[Path]: 32 | created_file_paths = [] 33 | for subdir in get_all_file_system_items(path, item_type=FileSystemItem.SUBDIR): 34 | init_file_path = subdir / "__init__.py" 35 | if not init_file_path.is_file(): 36 | init_file_path.touch() 37 | created_file_paths.append(init_file_path) 38 | 39 | return created_file_paths 40 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/reviewers/review_result.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from dataclasses import dataclass 4 | from typing import TYPE_CHECKING 5 | 6 | if TYPE_CHECKING: 7 | from pathlib import Path 8 | 9 | from hyperstyle.src.python.review.inspectors.common.issue.issue import BaseIssue, IssueDifficulty 10 | from hyperstyle.src.python.review.quality.model import Quality 11 | from hyperstyle.src.python.review.quality.penalty import Punisher 12 | 13 | 14 | @dataclass 15 | class ReviewResult: 16 | """ReviewResult contains a list of issues, as well as quality and punisher obtained with these issues.""" 17 | 18 | quality_by_difficulty: dict[IssueDifficulty, Quality] 19 | punisher_by_difficulty: dict[IssueDifficulty, Punisher] 20 | issues: list[BaseIssue] 21 | 22 | 23 | @dataclass 24 | class FileReviewResult(ReviewResult): 25 | """FileReviewResult contains the information needed to output about a particular inspected file.""" 26 | 27 | file_path: Path 28 | 29 | 30 | @dataclass 31 | class GeneralReviewResult(ReviewResult): 32 | """GeneralReviewResult contains the information needed to output about the entire inspected project.""" 33 | 34 | file_review_results: list[FileReviewResult] 35 | -------------------------------------------------------------------------------- /hyperstyle/src/python/review/reviewers/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/hyperstyle/src/python/review/reviewers/utils/__init__.py -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "code-review-tool", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "eslint": "./node_modules/eslint/bin/eslint.js" 7 | }, 8 | "dependencies": { 9 | "eslint-plugin-standard": "4.0.1" 10 | }, 11 | "devDependencies": { 12 | "eslint": "^7.19.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/test/__init__.py -------------------------------------------------------------------------------- /test/python/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pathlib import Path 4 | 5 | TEST_DATA_FOLDER = Path(__file__).parent.parent / "resources" 6 | -------------------------------------------------------------------------------- /test/python/functional_tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/test/python/functional_tests/__init__.py -------------------------------------------------------------------------------- /test/python/functional_tests/test_different_languages.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import subprocess 4 | 5 | from test.python.functional_tests.conftest import DATA_PATH, LocalCommandBuilder 6 | 7 | 8 | def test_python(local_command: LocalCommandBuilder) -> None: 9 | file_path = DATA_PATH / "different_languages" / "python" 10 | 11 | local_command.path = file_path 12 | process = subprocess.run( 13 | local_command.build(), 14 | capture_output=True, 15 | check=False, 16 | ) 17 | output = process.stdout.decode() 18 | 19 | assert process.returncode == 1 20 | assert "a.py" in output 21 | assert "b.py" in output 22 | 23 | 24 | def test_java(local_command: LocalCommandBuilder) -> None: 25 | file_path = DATA_PATH / "different_languages" / "java" 26 | 27 | local_command.path = file_path 28 | process = subprocess.run( 29 | local_command.build(), 30 | capture_output=True, 31 | check=False, 32 | ) 33 | output = process.stdout.decode() 34 | 35 | assert process.returncode == 1 36 | assert "First.java" in output 37 | assert "Second.java" in output 38 | 39 | 40 | def test_kotlin(local_command: LocalCommandBuilder) -> None: 41 | file_path = DATA_PATH / "different_languages" / "kotlin" 42 | 43 | local_command.path = file_path 44 | process = subprocess.run( 45 | local_command.build(), 46 | capture_output=True, 47 | check=False, 48 | ) 49 | output = process.stdout.decode() 50 | 51 | assert process.returncode == 1 52 | assert "main.kt" in output 53 | assert "person.kt" in output 54 | 55 | 56 | def test_all_java_inspectors(local_command: LocalCommandBuilder) -> None: 57 | file_path = DATA_PATH / "different_languages" / "java" 58 | 59 | local_command.path = file_path 60 | local_command.disable = [] 61 | process = subprocess.run( 62 | local_command.build(), 63 | capture_output=True, 64 | check=False, 65 | ) 66 | output = process.stdout.decode() 67 | 68 | assert process.returncode == 1 69 | assert "First.java" in output 70 | assert "Second.java" in output 71 | 72 | 73 | def test_go(local_command: LocalCommandBuilder) -> None: 74 | file_path = DATA_PATH / "different_languages" / "go" 75 | 76 | local_command.path = file_path 77 | local_command.disable = [] 78 | process = subprocess.run( 79 | local_command.build(), 80 | capture_output=True, 81 | check=False, 82 | ) 83 | output = process.stdout.decode() 84 | 85 | assert process.returncode == 1 86 | assert "a.go" in output 87 | assert "b.go" in output 88 | -------------------------------------------------------------------------------- /test/python/functional_tests/test_disable.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import subprocess 4 | 5 | from test.python.functional_tests.conftest import DATA_PATH, LocalCommandBuilder 6 | 7 | 8 | def test_disable_works(local_command: LocalCommandBuilder) -> None: 9 | file_path = DATA_PATH / "disable" / "contains_flake8_issues.py" 10 | 11 | local_command.path = file_path 12 | process = subprocess.run( 13 | local_command.build(), 14 | capture_output=True, 15 | check=False, 16 | ) 17 | output = process.stdout.decode() 18 | 19 | assert "FLAKE8" in output 20 | 21 | local_command.disable.append("flake8") 22 | process = subprocess.run( 23 | local_command.build(), 24 | capture_output=True, 25 | check=False, 26 | ) 27 | output = process.stdout.decode() 28 | 29 | assert "FLAKE8" not in output 30 | -------------------------------------------------------------------------------- /test/python/functional_tests/test_duplicates.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import re 4 | import subprocess 5 | 6 | from test.python.functional_tests.conftest import DATA_PATH, LocalCommandBuilder 7 | 8 | 9 | def test_allow_duplicates(local_command: LocalCommandBuilder) -> None: 10 | file_with_duplicate_issue_path = DATA_PATH / "duplicates" / "code_with_duplicate_issues.py" 11 | 12 | local_command.allow_duplicates = True 13 | local_command.path = file_with_duplicate_issue_path 14 | 15 | process = subprocess.run( 16 | local_command.build(), 17 | capture_output=True, 18 | check=False, 19 | ) 20 | stdout_allow_duplicates = process.stdout.decode() 21 | 22 | local_command.allow_duplicates = False 23 | 24 | process = subprocess.run( 25 | local_command.build(), 26 | capture_output=True, 27 | check=False, 28 | ) 29 | stdout_filter_duplicates = process.stdout.decode() 30 | 31 | flake8_var_issue_re = re.compile(r".*FLAKE8.*local variable \'var\'.*", re.DOTALL) 32 | pylint_var_issue_re = re.compile(r".*PYLINT.*Unused variable \'var\'.*", re.DOTALL) 33 | 34 | assert len(stdout_filter_duplicates) < len(stdout_allow_duplicates) 35 | assert flake8_var_issue_re.match(stdout_allow_duplicates) is not None 36 | assert pylint_var_issue_re.match(stdout_allow_duplicates) is not None 37 | assert (flake8_var_issue_re.match(stdout_filter_duplicates) is not None) ^ ( 38 | pylint_var_issue_re.match(stdout_filter_duplicates) is not None 39 | ) 40 | -------------------------------------------------------------------------------- /test/python/functional_tests/test_exit_code.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import subprocess 4 | from pathlib import Path 5 | 6 | from test.python.functional_tests.conftest import DATA_PATH, LocalCommandBuilder 7 | 8 | 9 | def test_exit_code_zero(local_command: LocalCommandBuilder) -> None: 10 | file_path = DATA_PATH / "exit_codes" / "no_issues.py" 11 | 12 | local_command.path = file_path 13 | process = subprocess.run( 14 | local_command.build(), 15 | capture_output=True, 16 | check=False, 17 | ) 18 | 19 | assert process.returncode == 0 20 | 21 | 22 | def test_exit_code_one(local_command: LocalCommandBuilder) -> None: 23 | file_path = DATA_PATH / "exit_codes" / "with_issues.py" 24 | 25 | local_command.path = file_path 26 | process = subprocess.run( 27 | local_command.build(), 28 | capture_output=True, 29 | check=False, 30 | ) 31 | 32 | assert process.returncode == 1 33 | 34 | 35 | def test_exit_code_two(local_command: LocalCommandBuilder) -> None: 36 | file_path = Path("no_such_file.py") 37 | 38 | local_command.path = file_path 39 | process = subprocess.run( 40 | local_command.build(), 41 | capture_output=True, 42 | check=False, 43 | ) 44 | 45 | assert process.returncode == 2 46 | -------------------------------------------------------------------------------- /test/python/functional_tests/test_file_or_project.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import subprocess 4 | 5 | from test.python.functional_tests.conftest import DATA_PATH, LocalCommandBuilder 6 | 7 | 8 | def test_inspect_file_works(local_command: LocalCommandBuilder) -> None: 9 | file_path = DATA_PATH / "file_or_project" / "file.py" 10 | 11 | local_command.path = file_path 12 | 13 | process = subprocess.run( 14 | local_command.build(), 15 | capture_output=True, 16 | check=False, 17 | ) 18 | output = process.stdout.decode() 19 | 20 | assert process.returncode == 1 21 | assert file_path.name in output 22 | 23 | 24 | def test_inspect_project_works(local_command: LocalCommandBuilder) -> None: 25 | file_path = DATA_PATH / "file_or_project" / "project" 26 | 27 | local_command.path = file_path 28 | 29 | process = subprocess.run( 30 | local_command.build(), 31 | capture_output=True, 32 | check=False, 33 | ) 34 | output = process.stdout.decode() 35 | 36 | assert process.returncode == 1 37 | assert "one.py" in output 38 | assert "other.py" in output 39 | 40 | 41 | def test_inspect_project_with_unknown_extensions_works(local_command: LocalCommandBuilder) -> None: 42 | file_path = DATA_PATH / "file_or_project" / "project_with_unknown_extensions" 43 | 44 | local_command.path = file_path 45 | 46 | process = subprocess.run( 47 | local_command.build(), 48 | capture_output=True, 49 | check=False, 50 | ) 51 | output = process.stdout.decode() 52 | 53 | assert process.returncode == 1 54 | assert "file.py" in output 55 | -------------------------------------------------------------------------------- /test/python/functional_tests/test_verbosity.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import json 4 | import subprocess 5 | 6 | from test.python.functional_tests.conftest import DATA_PATH, LocalCommandBuilder 7 | 8 | 9 | def test_disable_logs_text(local_command: LocalCommandBuilder) -> None: 10 | file_path = DATA_PATH / "verbosity" / "some_code.py" 11 | 12 | local_command.verbosity = 0 13 | local_command.path = file_path 14 | 15 | process = subprocess.run( 16 | local_command.build(), 17 | capture_output=True, 18 | check=False, 19 | ) 20 | output = process.stdout.decode() 21 | output = output.lower() 22 | 23 | assert " debug " not in output 24 | assert " info " not in output 25 | assert " error " not in output 26 | 27 | 28 | def test_disable_logs_json(local_command: LocalCommandBuilder) -> None: 29 | file_path = DATA_PATH / "verbosity" / "some_code.py" 30 | 31 | local_command.verbosity = 0 32 | local_command.format = "json" 33 | local_command.path = file_path 34 | 35 | process = subprocess.run( 36 | local_command.build(), 37 | capture_output=True, 38 | check=False, 39 | ) 40 | 41 | output = process.stdout.decode() 42 | json.loads(output) 43 | 44 | 45 | def test_enable_all_logs(local_command: LocalCommandBuilder) -> None: 46 | file_path = DATA_PATH / "verbosity" / "some_code.py" 47 | 48 | local_command.verbosity = 3 49 | local_command.path = file_path 50 | 51 | process = subprocess.run( 52 | local_command.build(), 53 | capture_output=True, 54 | check=False, 55 | ) 56 | output = process.stdout.decode() 57 | output = output.lower() 58 | 59 | assert " debug " in output 60 | -------------------------------------------------------------------------------- /test/python/inspectors/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from test.python import TEST_DATA_FOLDER 4 | 5 | CURRENT_TEST_DATA_FOLDER = TEST_DATA_FOLDER / "inspectors" 6 | 7 | PYTHON_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "python" 8 | 9 | JAVA_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "java" 10 | 11 | KOTLIN_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "kotlin" 12 | 13 | SPRING_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "spring" 14 | 15 | JS_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "js" 16 | 17 | GO_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "go" 18 | 19 | PYTHON_AST_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "python_ast" 20 | 21 | CHECKSTYLE_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "checkstyle" 22 | 23 | PMD_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "pmd" 24 | 25 | FLAKE_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "flake8" 26 | 27 | PYLINT_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "pylint" 28 | 29 | DETEKT_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "detekt" 30 | 31 | ESLINT_DATA_FOLDER = CURRENT_TEST_DATA_FOLDER / "eslint" 32 | 33 | GOLANG_LINT_FOLDER = CURRENT_TEST_DATA_FOLDER / "golang_lint" 34 | -------------------------------------------------------------------------------- /test/python/inspectors/test_common.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pytest 4 | 5 | from hyperstyle.src.python.review.inspectors.common.utils import ( 6 | _get_format_fields, 7 | contains_format_fields, 8 | contains_named_format_fields, 9 | ) 10 | 11 | GET_FORMAT_FIELDS_TEST_DATA = [ 12 | ("", []), 13 | ("abcdef", []), 14 | ("{{}}", []), 15 | ("{{0}}", []), 16 | ("{{false}}", []), 17 | ("{{abc:.3f}}", []), 18 | ("{}", [""]), 19 | ("{0}", ["0"]), 20 | ("{false}", ["false"]), 21 | ("{abc:.3f}", ["abc"]), 22 | ("{} {{}} {0} {abc}", ["", "0", "abc"]), 23 | ("This is a {f}-string!", ["f"]), 24 | ("{key: value for key, value in dct.items()}", ["key"]), 25 | ] 26 | 27 | 28 | @pytest.mark.parametrize(("string", "expected_fields"), GET_FORMAT_FIELDS_TEST_DATA) 29 | def test_get_format_fields(string: str, expected_fields: list[str]) -> None: 30 | assert _get_format_fields(string) == expected_fields 31 | 32 | 33 | CONTAINS_FORMAT_FIELDS_TEST_DATA = [ 34 | ("", False), 35 | ("abcdef", False), 36 | ("{{}}", False), 37 | ("{{0}}", False), 38 | ("{{false}}", False), 39 | ("{{abc:.3f}}", False), 40 | ("{}", True), 41 | ("{0}", True), 42 | ("{false}", True), 43 | ("{abc:.3f}", True), 44 | ("{} {{}} {0} {abc}", True), 45 | ("This is a {f}-string!", True), 46 | ("{key: value for key, value in dct.items()}", True), 47 | ] 48 | 49 | 50 | @pytest.mark.parametrize(("string", "expected"), CONTAINS_FORMAT_FIELDS_TEST_DATA) 51 | def test_contains_format_fields(string: str, expected: bool) -> None: 52 | assert contains_format_fields(string) == expected 53 | 54 | 55 | CONTAINS_NAMED_FORMAT_FIELDS_TEST_DATA = [ 56 | ("", False), 57 | ("abcdef", False), 58 | ("{{}}", False), 59 | ("{{0}}", False), 60 | ("{{false}}", False), 61 | ("{{abc:.3f}}", False), 62 | ("{}", False), 63 | ("{0}", False), 64 | ("{false}", True), 65 | ("{abc:.3f}", True), 66 | ("{} {{}} {0} {abc}", True), 67 | ("This is a {f}-string!", True), 68 | ("{key: value for key, value in dct.items()}", True), 69 | ] 70 | 71 | 72 | @pytest.mark.parametrize(("string", "expected"), CONTAINS_NAMED_FORMAT_FIELDS_TEST_DATA) 73 | def test_contains_named_format_fields(string: str, expected: bool) -> None: 74 | assert contains_named_format_fields(string) == expected 75 | -------------------------------------------------------------------------------- /test/python/inspectors/test_eslint_inspector.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pytest 4 | 5 | from hyperstyle.src.python.review.common.language import Language 6 | from hyperstyle.src.python.review.inspectors.common.issue.tips import get_cyclomatic_complexity_tip 7 | from hyperstyle.src.python.review.inspectors.eslint.eslint import ESLintInspector 8 | from hyperstyle.src.python.review.reviewers.utils.issues_filter import filter_low_measure_issues 9 | from test.python.inspectors import ESLINT_DATA_FOLDER, JS_DATA_FOLDER 10 | from test.python.inspectors.conftest import use_file_metadata 11 | 12 | FILE_NAMES_AND_N_ISSUES = [ 13 | ("case0_no_issues.js", 0), 14 | ("case1_with_issues.js", 7), 15 | ("case2_semi_node_and_unused.js", 5), 16 | ] 17 | 18 | 19 | @pytest.mark.parametrize(("file_name", "n_issues"), FILE_NAMES_AND_N_ISSUES) 20 | def test_file_with_issues(file_name: str, n_issues: int) -> None: 21 | inspector = ESLintInspector() 22 | 23 | path_to_file = JS_DATA_FOLDER / file_name 24 | with use_file_metadata(path_to_file) as file_metadata: 25 | issues = inspector.inspect(file_metadata.path, {}) 26 | issues = filter_low_measure_issues(issues, Language.JS) 27 | 28 | assert len(issues) == n_issues 29 | 30 | 31 | MEASURE_TEST_DATA = [ 32 | ("complexity", 13), 33 | ] 34 | 35 | 36 | @pytest.mark.parametrize(("origin_class", "expected_measure"), MEASURE_TEST_DATA) 37 | def test_measure_parse(origin_class: str, expected_measure: int) -> None: 38 | inspector = ESLintInspector() 39 | 40 | path_to_file = ESLINT_DATA_FOLDER / "issues" / f"{origin_class.replace('-', '_')}.js" 41 | with use_file_metadata(path_to_file) as file_metadata: 42 | issues = inspector.inspect(file_metadata.path, {}) 43 | 44 | issue = next(filter(lambda elem: elem.origin_class == origin_class, issues)) 45 | 46 | assert hasattr(issue, "measure") 47 | assert issue.measure() == expected_measure 48 | 49 | 50 | NEW_DESCRIPTION_TEST_DATA = [ 51 | ("complexity", get_cyclomatic_complexity_tip().format(13)), 52 | ] 53 | 54 | 55 | @pytest.mark.parametrize(("origin_class", "expected_description"), NEW_DESCRIPTION_TEST_DATA) 56 | def test_new_issue_description(origin_class: str, expected_description: str) -> None: 57 | inspector = ESLintInspector() 58 | 59 | path_to_file = ESLINT_DATA_FOLDER / "issues" / f"{origin_class.replace('-', '_')}.js" 60 | with use_file_metadata(path_to_file) as file_metadata: 61 | issues = inspector.inspect(file_metadata.path, {}) 62 | 63 | issue = next(filter(lambda elem: elem.origin_class == origin_class, issues)) 64 | 65 | assert issue.description == expected_description 66 | -------------------------------------------------------------------------------- /test/python/inspectors/test_out_of_range_issues.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pathlib import Path 4 | 5 | from hyperstyle.src.python.review.inspectors.common.inspector.inspector_type import InspectorType 6 | from hyperstyle.src.python.review.inspectors.common.issue.issue import ( 7 | BaseIssue, 8 | CodeIssue, 9 | IssueDifficulty, 10 | IssueType, 11 | ) 12 | from hyperstyle.src.python.review.reviewers.common import filter_out_of_range_issues 13 | 14 | DEFAULT_PATH = Path("test_out_of_range_issues.py") 15 | 16 | 17 | def create_code_issue_by_line(line_no: int) -> BaseIssue: 18 | return CodeIssue( 19 | file_path=DEFAULT_PATH, 20 | line_no=line_no, 21 | description="", 22 | inspector_type=InspectorType.FLAKE8, 23 | type=IssueType.CODE_STYLE, 24 | column_no=1, 25 | origin_class="", 26 | difficulty=IssueDifficulty.EASY, 27 | ) 28 | 29 | 30 | def test_out_of_range_issues_when_no_issues() -> None: 31 | issues = [] 32 | 33 | assert filter_out_of_range_issues(issues) == [] 34 | assert filter_out_of_range_issues(issues, start_line=2) == [] 35 | assert filter_out_of_range_issues(issues, end_line=4) == [] 36 | assert filter_out_of_range_issues(issues, start_line=2, end_line=4) == [] 37 | 38 | 39 | def test_out_of_range_issues_when_some_out_of_range_issues() -> None: 40 | issues = [ 41 | create_code_issue_by_line(line_no) 42 | for line_no in range(1, 6) # 1, 2, 3, 4, 5 43 | ] 44 | 45 | assert filter_out_of_range_issues(issues) == issues 46 | assert filter_out_of_range_issues(issues, start_line=2) == issues[1:5] 47 | assert filter_out_of_range_issues(issues, end_line=4) == issues[:4] 48 | assert filter_out_of_range_issues(issues, start_line=2, end_line=4) == issues[1:4] 49 | assert filter_out_of_range_issues(issues, start_line=4, end_line=8) == [issues[3], issues[4]] 50 | assert filter_out_of_range_issues(issues, start_line=6, end_line=10) == [] 51 | 52 | 53 | def test_out_of_range_issues_when_the_same_borders() -> None: 54 | first_line_issues = [ 55 | create_code_issue_by_line(1), 56 | create_code_issue_by_line(1), 57 | create_code_issue_by_line(1), 58 | ] 59 | 60 | assert filter_out_of_range_issues(first_line_issues, start_line=1, end_line=1) == first_line_issues 61 | 62 | assert filter_out_of_range_issues(first_line_issues, start_line=2, end_line=2) == [] 63 | -------------------------------------------------------------------------------- /test/python/inspectors/test_radon_inspector.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from textwrap import dedent 4 | 5 | import pytest 6 | 7 | from hyperstyle.src.python.review.common.language import Language 8 | from hyperstyle.src.python.review.inspectors.common.issue.issue import IssueType 9 | from hyperstyle.src.python.review.inspectors.common.issue.tips import get_maintainability_index_tip 10 | from hyperstyle.src.python.review.inspectors.radon.radon import RadonInspector 11 | from hyperstyle.src.python.review.reviewers.utils.issues_filter import filter_low_measure_issues 12 | from test.python.inspectors import PYTHON_DATA_FOLDER 13 | from test.python.inspectors.conftest import use_file_metadata 14 | 15 | FILE_NAMES_AND_N_ISSUES = [ 16 | ("case13_complex_logic.py", 1), 17 | ("case13_complex_logic_2.py", 1), 18 | ("case8_good_class.py", 0), 19 | ] 20 | 21 | 22 | @pytest.mark.parametrize(("file_name", "n_issues"), FILE_NAMES_AND_N_ISSUES) 23 | def test_file_with_issues(file_name: str, n_issues: int) -> None: 24 | inspector = RadonInspector() 25 | 26 | path_to_file = PYTHON_DATA_FOLDER / file_name 27 | with use_file_metadata(path_to_file) as file_metadata: 28 | issues = inspector.inspect(file_metadata.path, {}) 29 | issues = filter_low_measure_issues(issues, Language.PYTHON) 30 | 31 | assert len(issues) == n_issues 32 | 33 | 34 | def test_mi_parse() -> None: 35 | file_name = "test.py" 36 | output = f"""\ 37 | {file_name} - C (4.32) 38 | {file_name} - B (13.7) 39 | {file_name} - A (70.0) 40 | """ 41 | output = dedent(output) 42 | 43 | issues = RadonInspector.mi_parse(output) 44 | 45 | assert all(str(issue.file_path) == file_name for issue in issues) 46 | assert [issue.line_no for issue in issues] == [1, 1, 1] 47 | assert [issue.column_no for issue in issues] == [1, 1, 1] 48 | assert [issue.description for issue in issues] == [get_maintainability_index_tip()] * 3 49 | assert [issue.type for issue in issues] == [ 50 | IssueType.MAINTAINABILITY, 51 | IssueType.MAINTAINABILITY, 52 | IssueType.MAINTAINABILITY, 53 | ] 54 | assert hasattr(issues[0], "maintainability_lack") 55 | assert issues[0].maintainability_lack == 95 56 | 57 | assert hasattr(issues[1], "maintainability_lack") 58 | assert issues[1].maintainability_lack == 86 59 | 60 | assert hasattr(issues[2], "maintainability_lack") 61 | assert issues[2].maintainability_lack == 30 62 | -------------------------------------------------------------------------------- /test/python/quality/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/test/python/quality/__init__.py -------------------------------------------------------------------------------- /test/resources/functional_tests/different_languages/go/a.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func hello(name string) string { 6 | if "Jerry" == name { 7 | return "Hello, Jerry!" 8 | } else { 9 | return "Hello, non-Jerry!" 10 | } 11 | return "Hello?" 12 | } 13 | 14 | func main() { 15 | var name string 16 | fmt.Scan(&name) 17 | fmt.Println(hello(name)) 18 | } 19 | -------------------------------------------------------------------------------- /test/resources/functional_tests/different_languages/go/b.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "math" 5 | ) 6 | 7 | func hypotenuse(a int, b int) float64 { 8 | return math.Sqrt(math.Pow(float64(a), 2) + math.Pow(float64(b), 2)) 9 | } 10 | -------------------------------------------------------------------------------- /test/resources/functional_tests/different_languages/go/go.mod: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | go 1.18 4 | -------------------------------------------------------------------------------- /test/resources/functional_tests/different_languages/java/src/First.java: -------------------------------------------------------------------------------- 1 | public class First{ 2 | int x = 5; 3 | } -------------------------------------------------------------------------------- /test/resources/functional_tests/different_languages/java/src/Second.java: -------------------------------------------------------------------------------- 1 | public class Second{ 2 | 3 | public static void main() { 4 | First f = new First(); 5 | } 6 | 7 | } -------------------------------------------------------------------------------- /test/resources/functional_tests/different_languages/kotlin/main.kt: -------------------------------------------------------------------------------- 1 | fun main(args:Array) { 2 | val a = Person() 3 | val b = Person() 4 | println("${a.age} ${b.age}") // Prints "32 32" 5 | a.age = 42 6 | println("${a.age} ${b.age}") // Prints "42 32" 7 | } -------------------------------------------------------------------------------- /test/resources/functional_tests/different_languages/kotlin/person.kt: -------------------------------------------------------------------------------- 1 | class Person { 2 | var name ="Anne" 3 | var age = 32 4 | } -------------------------------------------------------------------------------- /test/resources/functional_tests/different_languages/python/a.py: -------------------------------------------------------------------------------- 1 | def GREETING(): 2 | print('hi!') 3 | 4 | 5 | class myclass: 6 | 7 | def __init__(self, a, b, C): 8 | self.A = a 9 | self.B = b 10 | self.C = C 11 | 12 | def myFun(self): 13 | print('hello 1') 14 | 15 | def my_fun(self, QQ): 16 | print('hello 2' + QQ) 17 | 18 | @classmethod 19 | def test_fun(first): 20 | print('hello 3') 21 | 22 | 23 | valid_variable = 'ok' 24 | invalidVariable = 'invalid' 25 | 26 | print(valid_variable) 27 | print(invalidVariable) 28 | -------------------------------------------------------------------------------- /test/resources/functional_tests/different_languages/python/b.py: -------------------------------------------------------------------------------- 1 | 2 | def is_even(number): 3 | return number % 2 == 0 4 | 5 | 6 | n = int(input()) 7 | for i in range(n): 8 | print(i) 9 | -------------------------------------------------------------------------------- /test/resources/functional_tests/difficulty_levels/file_with_all_difficulty_levels.py: -------------------------------------------------------------------------------- 1 | from math import sqrt 2 | 3 | MUTABLE_CONSTANT = {"1": 1, "2": 2} 4 | 5 | class BadClass: 6 | def __init__(self, x: int, y: int): 7 | self.x = x 8 | self.y = y 9 | 10 | @staticmethod 11 | def Length(x: int, y: int) -> float: 12 | return sqrt(x ** 2 + y ** 2) 13 | 14 | @staticmethod 15 | def dot(self_x: int, self_y: int, other_x: int, other_y: int) -> int: 16 | return self_x * other_x + self_y * other_y 17 | 18 | @staticmethod 19 | def plus(self_x: int, self_y: int, other_x: int, other_y: int) -> 'BadClass': 20 | return BadClass(self_x + other_x, self_y + other_y) 21 | 22 | @staticmethod 23 | def minus(self_x: int, self_y: int, other_x: int, other_y: int) -> 'BadClass': 24 | return BadClass(self_x - other_x, self_y - other_y) -------------------------------------------------------------------------------- /test/resources/functional_tests/difficulty_levels/file_with_only_easy_issues.py: -------------------------------------------------------------------------------- 1 | def MAIN(Number): 2 | if Number > 0: 3 | return Number 4 | 5 | return 0 6 | 7 | 8 | if __name__ == "__main__": 9 | print( 10 | "Hello, World") 11 | 12 | MAIN(0) 13 | -------------------------------------------------------------------------------- /test/resources/functional_tests/difficulty_levels/file_with_only_hard_issues.py: -------------------------------------------------------------------------------- 1 | from math import sqrt 2 | 3 | 4 | class BadClass: 5 | def __init__(self, x: int, y: int): 6 | self.x = x 7 | self.y = y 8 | 9 | @staticmethod 10 | def length(x: int, y: int) -> float: 11 | return sqrt(x ** 2 + y ** 2) 12 | 13 | @staticmethod 14 | def dot(self_x: int, self_y: int, other_x: int, other_y: int) -> int: 15 | return self_x * other_x + self_y * other_y 16 | 17 | @staticmethod 18 | def plus(self_x: int, self_y: int, other_x: int, other_y: int) -> 'BadClass': 19 | return BadClass(self_x + other_x, self_y + other_y) 20 | 21 | @staticmethod 22 | def minus(self_x: int, self_y: int, other_x: int, other_y: int) -> 'BadClass': 23 | return BadClass(self_x - other_x, self_y - other_y) 24 | 25 | 26 | if __name__ == "__main__": 27 | print("Hello, World!") 28 | -------------------------------------------------------------------------------- /test/resources/functional_tests/difficulty_levels/file_with_only_medium_issues.py: -------------------------------------------------------------------------------- 1 | MUTABLE_CONSTANT = {"1": 1, "2": 2} 2 | 3 | PI = 3.14 4 | DOUBLE_PI = 6.28 5 | E = 2.71 6 | 7 | 8 | def function_with_bad_try(b, c): 9 | result = None 10 | 11 | try: 12 | result = b / c 13 | except Exception: 14 | print("It's fine") 15 | 16 | return result 17 | 18 | 19 | def bad_generator(some_value): 20 | if some_value: 21 | raise StopIteration 22 | yield 1 23 | 24 | 25 | if __name__ == "__main__": 26 | 27 | print("Hello, World!") 28 | -------------------------------------------------------------------------------- /test/resources/functional_tests/difficulty_levels/file_without_issues.py: -------------------------------------------------------------------------------- 1 | if __name__ == '__main__': 2 | print("Hello, world") -------------------------------------------------------------------------------- /test/resources/functional_tests/disable/contains_flake8_issues.py: -------------------------------------------------------------------------------- 1 | 2 | a = int(input()) 3 | b = int(input()) 4 | c = int(input()) 5 | d = int(input()) 6 | 7 | if a > b: 8 | print('a > b') 9 | 10 | if a > b and a > b: 11 | print('a > b again') 12 | 13 | if a > b and a < d: 14 | print('b < a < d') 15 | 16 | if not a > b: 17 | print('not a > b') 18 | 19 | if b < a < d: 20 | print('b < a < d again') 21 | 22 | if a > b == True: 23 | print('a > b and True') 24 | 25 | if True: 26 | print('qqq') 27 | 28 | enabled = False # It does not work now 29 | if a > b and b < c and c > d or c < a and enabled: 30 | print('Too complex expression') 31 | -------------------------------------------------------------------------------- /test/resources/functional_tests/duplicates/code_with_duplicate_issues.py: -------------------------------------------------------------------------------- 1 | a, b = input().split() 2 | print(int(a) + int(b)) 3 | 4 | 5 | def fooBar(): 6 | var = 1 7 | print( 8 | "Hello" 9 | "World" 10 | ) 11 | 12 | 13 | x = 42 # noqa: E222,E305 14 | text = "This line is longer than 99 characters. This line is longer than 99 characters. This line is longer than 99 characters" 15 | pass -------------------------------------------------------------------------------- /test/resources/functional_tests/exit_codes/no_issues.py: -------------------------------------------------------------------------------- 1 | def say_hello(): 2 | print('hello') 3 | 4 | 5 | if __name__ == '__main__': 6 | say_hello() 7 | -------------------------------------------------------------------------------- /test/resources/functional_tests/exit_codes/with_issues.py: -------------------------------------------------------------------------------- 1 | a, b, c = (input(),input(),input()) 2 | print(f'{a} {b} {c}') 3 | 4 | print('1', '2', '3', sep = '|') 5 | 6 | result = int(a)+10 7 | print(result) -------------------------------------------------------------------------------- /test/resources/functional_tests/file_or_project/file.py: -------------------------------------------------------------------------------- 1 | def grade(score, max_score): 2 | return score * 100 / max_score 3 | 4 | 5 | score = int(input()) 6 | max_score = int(input()) 7 | 8 | grade(score, max_score) -------------------------------------------------------------------------------- /test/resources/functional_tests/file_or_project/project/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/test/resources/functional_tests/file_or_project/project/__init__.py -------------------------------------------------------------------------------- /test/resources/functional_tests/file_or_project/project/one.py: -------------------------------------------------------------------------------- 1 | from other import do_something_useless 2 | 3 | if __name__ == '__main__': 4 | do_something_useless() -------------------------------------------------------------------------------- /test/resources/functional_tests/file_or_project/project/other.py: -------------------------------------------------------------------------------- 1 | def do_something_useless(): 2 | a = 1 3 | b = 2 4 | c = 3 -------------------------------------------------------------------------------- /test/resources/functional_tests/file_or_project/project_with_unknown_extensions/file.abc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/test/resources/functional_tests/file_or_project/project_with_unknown_extensions/file.abc -------------------------------------------------------------------------------- /test/resources/functional_tests/file_or_project/project_with_unknown_extensions/file.py: -------------------------------------------------------------------------------- 1 | def FunctionWithIssue(): 2 | pass 3 | 4 | answer = 42 5 | print(answer) 6 | -------------------------------------------------------------------------------- /test/resources/functional_tests/file_or_project/project_with_unknown_extensions/file.xyz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/test/resources/functional_tests/file_or_project/project_with_unknown_extensions/file.xyz -------------------------------------------------------------------------------- /test/resources/functional_tests/lines_range/code_with_multiple_issues.py: -------------------------------------------------------------------------------- 1 | a=10 2 | b=20 3 | print(b) 4 | c=a + b 5 | print(c) 6 | -------------------------------------------------------------------------------- /test/resources/functional_tests/verbosity/some_code.py: -------------------------------------------------------------------------------- 1 | 2 | def fun(param): 3 | a = 10 4 | b = 20 5 | c = 30 6 | print(c) 7 | d = 40 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/empty_file.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/test/resources/inspectors/checkstyle/empty_file.xml -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/issues/BooleanExpressionComplexityCheck.java: -------------------------------------------------------------------------------- 1 | class ComplexBooleanExpression { 2 | public static void main(String[] args) { 3 | Scanner scanner = new Scanner(System.in); 4 | 5 | int a = scanner.nextInt(); 6 | int b = scanner.nextInt(); 7 | int c = scanner.nextInt(); 8 | int d = scanner.nextInt(); 9 | 10 | if (a > b && a > b && a > c && a > d) { 11 | System.out.println("'a' is the largest"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/issues/CyclomaticComplexityCheck.java: -------------------------------------------------------------------------------- 1 | class ComplexBooleanExpression { 2 | public static void main(String[] args) { 3 | Scanner scanner = new Scanner(System.in); 4 | 5 | int a = scanner.nextInt(); 6 | int b = scanner.nextInt(); 7 | int c = scanner.nextInt(); 8 | int d = scanner.nextInt(); 9 | 10 | if (a > b) { 11 | if (a > c) { 12 | if (a > d) { 13 | System.out.println("'a' is the largest"); 14 | } 15 | } 16 | } 17 | 18 | if (b > a) { 19 | if (b > c) { 20 | if (b > d) { 21 | System.out.println("'b' is the largest"); 22 | } 23 | } 24 | } 25 | 26 | if (c > a) { 27 | if (c > b) { 28 | if (c > d) { 29 | System.out.println("'c' is the largest"); 30 | } 31 | } 32 | } 33 | 34 | if (d > a) { 35 | if (d > b) { 36 | if (d > c) { 37 | System.out.println("'d' is the largest"); 38 | } 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/issues/JavaNCSSCheck.java: -------------------------------------------------------------------------------- 1 | class LongHelloWorld { 2 | public static void main(String[] args) { 3 | System.out.println("H"); 4 | System.out.println("e"); 5 | System.out.println("l"); 6 | System.out.println("l"); 7 | System.out.println("o"); 8 | System.out.println(","); 9 | System.out.println(" "); 10 | System.out.println("W"); 11 | System.out.println("o"); 12 | System.out.println("r"); 13 | System.out.println("l"); 14 | System.out.println("d"); 15 | System.out.println("!"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/issues/LineLengthCheck.java: -------------------------------------------------------------------------------- 1 | class LongLine { 2 | public static void main(String[] args) { 3 | System.out.println("Wow! This line is soooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo long..."); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/issues/MagicNumberCheck.java: -------------------------------------------------------------------------------- 1 | class ComplexBooleanExpression { 2 | public static void main(String[] args) { 3 | System.out.println(42); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/multi_file_project_with_metric_issues.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | 10 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/multi_file_project_without_issues.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/multi_file_project_without_metric_issues.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | 11 | 14 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/single_file_project_with_metric_issues.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/single_file_project_without_issues.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/resources/inspectors/checkstyle/single_file_project_without_metric_issues.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/resources/inspectors/detekt/issues/ComplexCondition.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | val a = readLine()?.toInt() ?: 0 3 | val b = readLine()?.toInt() ?: 0 4 | val c = readLine()?.toInt() ?: 0 5 | val d = readLine()?.toInt() ?: 0 6 | 7 | if (a > b && a > b && a > c && a > d) { 8 | println(a) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/resources/inspectors/detekt/issues/ComplexMethod.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | val a = readLine()?.toInt() ?: 0 3 | val b = readLine()?.toInt() ?: 0 4 | val c = readLine()?.toInt() ?: 0 5 | val d = readLine()?.toInt() ?: 0 6 | 7 | if (a > b) { 8 | if (a > c) { 9 | if (a > d) { 10 | println("'a' is the largest"); 11 | } 12 | } 13 | } 14 | 15 | if (b > a) { 16 | if (b > c) { 17 | if (b > d) { 18 | println("'b' is the largest"); 19 | } 20 | } 21 | } 22 | 23 | if (c > a) { 24 | if (c > b) { 25 | if (c > d) { 26 | println("'c' is the largest"); 27 | } 28 | } 29 | } 30 | 31 | if (d > a) { 32 | if (d > b) { 33 | if (d > c) { 34 | println("'d' is the largest"); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test/resources/inspectors/detekt/issues/LongMethod.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | println("H") 3 | println("e") 4 | println("l") 5 | println("l") 6 | println("o") 7 | println(",") 8 | println(" ") 9 | println("W") 10 | println("o") 11 | println("r") 12 | println("l") 13 | println("d") 14 | println("!") 15 | } 16 | -------------------------------------------------------------------------------- /test/resources/inspectors/detekt/issues/MagicNumber.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | println(42) 3 | } 4 | -------------------------------------------------------------------------------- /test/resources/inspectors/eslint/issues/complexity.js: -------------------------------------------------------------------------------- 1 | function complexFunction(a, b, c, d) { 2 | if (a > b) { 3 | if (a > c) { 4 | if (a > d) { 5 | console.log("'a' is the largest!") 6 | } 7 | } 8 | } 9 | 10 | if (b > a) { 11 | if (b > c) { 12 | if (b > d) { 13 | console.log("'b' is the largest!") 14 | } 15 | } 16 | } 17 | 18 | if (c > a) { 19 | if (c > b) { 20 | if (c > d) { 21 | console.log("'c' is the largest!") 22 | } 23 | } 24 | } 25 | 26 | if (d > a) { 27 | if (d > b) { 28 | if (d > c) { 29 | console.log("'d' is the largest!") 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/resources/inspectors/flake8/issues/b007.py: -------------------------------------------------------------------------------- 1 | n = int(input()) 2 | for i in range(n): 3 | print(n) 4 | -------------------------------------------------------------------------------- /test/resources/inspectors/flake8/issues/c901.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n = int(input()) 3 | if n > 0: 4 | print(f'{n} > 0') 5 | elif n < 0: 6 | print(f'{n} < 0') 7 | else: 8 | print(f'{n} = 0') 9 | -------------------------------------------------------------------------------- /test/resources/inspectors/flake8/issues/e501.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | n = input() 3 | if len(n) > 120: 4 | print('Wow! This is such a looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line.') 5 | -------------------------------------------------------------------------------- /test/resources/inspectors/flake8/issues/h601.py: -------------------------------------------------------------------------------- 1 | class Foo: 2 | def __init__(self, a: int, b: int): 3 | self.a = a 4 | self.b = b 5 | -------------------------------------------------------------------------------- /test/resources/inspectors/flake8/issues/wps350.py: -------------------------------------------------------------------------------- 1 | x = int(input()) 2 | x = x * x 3 | -------------------------------------------------------------------------------- /test/resources/inspectors/flake8/issues/wps432.py: -------------------------------------------------------------------------------- 1 | print(42) 2 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case0_empty.go: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/test/resources/inspectors/go/case0_empty.go -------------------------------------------------------------------------------- /test/resources/inspectors/go/case10_gocritic_issues.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // gocritic-switchTrue 7 | switch true { 8 | case true: 9 | fmt.Println("Hello, True!") 10 | case false: 11 | fmt.Println("Hello, False!") 12 | default: 13 | fmt.Println("Hello, default!") 14 | } 15 | 16 | // gocritic-newDeref 17 | x := *new(int) 18 | 19 | // gocritic-assignOP 20 | x = x * 2 21 | 22 | fmt.Println(x) 23 | } 24 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case11_gosimple_issues.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // gosimple-S1006 7 | for true { 8 | fmt.Println("I am an infinity loop.") 9 | } 10 | 11 | var input string 12 | _, _ = fmt.Scan(&input) 13 | 14 | // gosimple-S1039 15 | input = fmt.Sprintf("My name is Jeff.") 16 | 17 | // gosimple-S1029 18 | for _, r := range []rune(input) { 19 | fmt.Println(r) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case12_stylecheck_issues.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var input int 7 | _, _ = fmt.Scan(&input) 8 | 9 | // stylecheck-ST1017 10 | if 1 == input { 11 | fmt.Println("input == 1") 12 | } 13 | 14 | // stylecheck-ST1015 15 | switch { 16 | case input > 0: 17 | fmt.Println("input > 0") 18 | default: 19 | fmt.Println("input == 0") 20 | case input < 0: 21 | fmt.Println("input < 0") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case13_staticcheck_issues.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // staticcheck-SA4026 9 | const TEST = -0.0 10 | 11 | func main() { 12 | fmt.Println(TEST) 13 | 14 | // staticcheck-SA4013 15 | if !!true { 16 | fmt.Println("Not true.") 17 | } else { 18 | fmt.Println("Not not true.") 19 | } 20 | 21 | // staticcheck-SA1018 22 | fmt.Println(strings.Replace("Hello, World!", "l", "", 0)) 23 | } 24 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case14_whitespace.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func printHelloWorld() { 6 | 7 | 8 | fmt.Println("Hello, world!") 9 | 10 | 11 | } 12 | 13 | 14 | 15 | 16 | 17 | func main() { 18 | 19 | 20 | 21 | printHelloWorld() 22 | 23 | 24 | 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case15_deadcode.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var unusedVar int 6 | 7 | func unusedFunction() { 8 | 9 | } 10 | 11 | func factorial(n int) int { 12 | if n == 0 { 13 | return 1 14 | } 15 | 16 | return n * factorial(n-1) 17 | } 18 | 19 | func main() { 20 | fmt.Println("Hello, world!") 21 | } 22 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case16_errcheck.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io/ioutil" 7 | ) 8 | 9 | func returnError() error { 10 | return errors.New("empty name") 11 | } 12 | 13 | func main() { 14 | fmt.Println("Ignoring error") 15 | 16 | returnError() 17 | _ = returnError() 18 | 19 | ioutil.ReadFile("test.go") 20 | content, _ := ioutil.ReadFile("test.go") 21 | 22 | var someInterface interface{} 23 | stringInterface1 := someInterface.(string) 24 | stringInterface1 = someInterface.(string) 25 | 26 | stringInterface2, _ := someInterface.(string) 27 | stringInterface2, _ = someInterface.(string) 28 | 29 | fmt.Println(content, stringInterface1, stringInterface2) 30 | } 31 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case17_magic_numbers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func printNumber(number int) { 6 | fmt.Println(number) 7 | } 8 | 9 | func main() { 10 | printNumber(42) 11 | 12 | var input int 13 | fmt.Scan(&input) 14 | 15 | if input == 1 { 16 | printNumber(input) 17 | } 18 | 19 | switch input { 20 | case 0: 21 | printNumber(input) 22 | case 1: 23 | printNumber(input) 24 | case 2: 25 | printNumber(input) 26 | case 3: 27 | printNumber(input) 28 | default: 29 | fmt.Println("I don't want to print this number!") 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case18_generics.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func generic_sum[K comparable, V int | float64](m map[K]V) V { 6 | var s V 7 | for _, v := range m { 8 | s += v 9 | } 10 | return s 11 | } 12 | 13 | func main() { 14 | fmt.Println(generic_sum(map[string]int{"first": 42, "second": 69})) 15 | fmt.Println(generic_sum(map[string]float64{"first": 42.69, "second": 69.42})) 16 | } 17 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case1_simple_valid_program.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("Hello, World!") 7 | } 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case2_program_with_syntax_errors.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | a := 42 10 | fmt.Println("Hello, World!") 11 | } 12 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case3_issues_with_related_information.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func hello(name string) { 6 | name = "Jerry" // staticcheck-SA4009 7 | fmt.Printf("Hello, %s!", name) 8 | } 9 | 10 | func main() { 11 | hello("Teddy") 12 | } 13 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case4_cyclomatic_complexity.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func plus(number int, bias int) int { 6 | if number == 0 && bias == 0 { 7 | return 0 8 | } 9 | 10 | if number == 0 && bias == 1 { 11 | return 1 12 | } 13 | 14 | if number == 0 && bias == 2 { 15 | return 2 16 | } 17 | 18 | if number == 1 && bias == 0 { 19 | return 1 20 | } 21 | 22 | if number == 1 && bias == 1 { 23 | return 2 24 | } 25 | 26 | if number == 1 && bias == 2 { 27 | return 3 28 | } 29 | 30 | if number == 2 && bias == 0 { 31 | return 2 32 | } 33 | 34 | if number == 2 && bias == 1 { 35 | return 3 36 | } 37 | 38 | if number == 2 && bias == 2 { 39 | return 4 40 | } 41 | 42 | return -1 43 | } 44 | 45 | func main() { 46 | fmt.Println(plus(1, 1)) 47 | } 48 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case5_function_length.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func printNumbersFrom0To99() { 6 | fmt.Println(0) 7 | fmt.Println(1) 8 | fmt.Println(2) 9 | fmt.Println(3) 10 | fmt.Println(4) 11 | fmt.Println(5) 12 | fmt.Println(6) 13 | fmt.Println(7) 14 | fmt.Println(8) 15 | fmt.Println(9) 16 | fmt.Println(10) 17 | fmt.Println(11) 18 | fmt.Println(12) 19 | fmt.Println(13) 20 | fmt.Println(14) 21 | fmt.Println(15) 22 | fmt.Println(16) 23 | fmt.Println(17) 24 | fmt.Println(18) 25 | fmt.Println(19) 26 | fmt.Println(20) 27 | fmt.Println(21) 28 | fmt.Println(22) 29 | fmt.Println(23) 30 | fmt.Println(24) 31 | fmt.Println(25) 32 | fmt.Println(26) 33 | fmt.Println(27) 34 | fmt.Println(28) 35 | fmt.Println(29) 36 | fmt.Println(30) 37 | fmt.Println(31) 38 | fmt.Println(32) 39 | fmt.Println(33) 40 | fmt.Println(34) 41 | fmt.Println(35) 42 | fmt.Println(36) 43 | fmt.Println(37) 44 | fmt.Println(38) 45 | fmt.Println(39) 46 | fmt.Println(40) 47 | fmt.Println(41) 48 | fmt.Println(42) 49 | fmt.Println(43) 50 | fmt.Println(44) 51 | fmt.Println(45) 52 | fmt.Println(46) 53 | fmt.Println(47) 54 | fmt.Println(48) 55 | fmt.Println(49) 56 | fmt.Println(50) 57 | fmt.Println(51) 58 | fmt.Println(52) 59 | fmt.Println(53) 60 | fmt.Println(54) 61 | fmt.Println(55) 62 | fmt.Println(56) 63 | fmt.Println(57) 64 | fmt.Println(58) 65 | fmt.Println(59) 66 | fmt.Println(60) 67 | fmt.Println(61) 68 | fmt.Println(62) 69 | fmt.Println(63) 70 | fmt.Println(64) 71 | fmt.Println(65) 72 | fmt.Println(66) 73 | fmt.Println(67) 74 | fmt.Println(68) 75 | fmt.Println(69) 76 | fmt.Println(70) 77 | fmt.Println(71) 78 | fmt.Println(72) 79 | fmt.Println(73) 80 | fmt.Println(74) 81 | fmt.Println(75) 82 | fmt.Println(76) 83 | fmt.Println(77) 84 | fmt.Println(78) 85 | fmt.Println(79) 86 | fmt.Println(80) 87 | fmt.Println(81) 88 | fmt.Println(82) 89 | fmt.Println(83) 90 | fmt.Println(84) 91 | fmt.Println(85) 92 | fmt.Println(86) 93 | fmt.Println(87) 94 | fmt.Println(88) 95 | fmt.Println(89) 96 | fmt.Println(90) 97 | fmt.Println(91) 98 | fmt.Println(92) 99 | fmt.Println(93) 100 | fmt.Println(94) 101 | fmt.Println(95) 102 | fmt.Println(96) 103 | fmt.Println(97) 104 | fmt.Println(98) 105 | fmt.Println(99) 106 | } 107 | 108 | func main() { 109 | printNumbersFrom0To99() 110 | } 111 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case6_line_length.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func printVeryLongLine() { 6 | fmt.Println("Wow! This line is soooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo long.") 7 | } 8 | 9 | func main() { 10 | printVeryLongLine() 11 | } 12 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case8_govet_issues.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | // govet-printf 10 | fmt.Printf("%b", "Hello!") 11 | 12 | // govet-unusedresult 13 | var buf bytes.Buffer 14 | buf.String() 15 | 16 | return 17 | 18 | // govet-unreachable 19 | fmt.Print("Unreachable!") 20 | } 21 | -------------------------------------------------------------------------------- /test/resources/inspectors/go/case9_revive_issues.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // revive-var-naming 7 | var this_is_int int 8 | _, _ = fmt.Scan(&this_is_int) 9 | 10 | // revive-bool-literal-in-expr and revive-identical-branches 11 | if this_is_int > 0 && true { 12 | fmt.Println("this_is_int > 0") 13 | } else { 14 | fmt.Println("this_is_int > 0") 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/resources/inspectors/golang_lint/empty_file.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/test/resources/inspectors/golang_lint/empty_file.json -------------------------------------------------------------------------------- /test/resources/inspectors/golang_lint/issues/cyclop.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var a int 7 | var b int 8 | var c int 9 | var d int 10 | 11 | fmt.Scan(&a) 12 | fmt.Scan(&b) 13 | fmt.Scan(&c) 14 | fmt.Scan(&d) 15 | 16 | if a > b { 17 | if a > c { 18 | if a > d { 19 | fmt.Println("'a' is the largest.") 20 | } 21 | } 22 | } 23 | 24 | if b > a { 25 | if b > c { 26 | if b > d { 27 | fmt.Println("'b' is the largest.") 28 | } 29 | } 30 | } 31 | 32 | if c > a { 33 | if c > b { 34 | if c > d { 35 | fmt.Println("'c' is the largest.") 36 | } 37 | } 38 | } 39 | 40 | if d > a { 41 | if d > b { 42 | if d > c { 43 | fmt.Println("'d' is the largest.") 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/resources/inspectors/golang_lint/issues/funlen.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("H") 7 | fmt.Println("e") 8 | fmt.Println("l") 9 | fmt.Println("l") 10 | fmt.Println("o") 11 | fmt.Println(",") 12 | fmt.Println(" ") 13 | fmt.Println("W") 14 | fmt.Println("o") 15 | fmt.Println("r") 16 | fmt.Println("l") 17 | fmt.Println("d") 18 | fmt.Println("!") 19 | } 20 | -------------------------------------------------------------------------------- /test/resources/inspectors/golang_lint/issues/gomnd.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Print(42) 7 | } 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/golang_lint/issues/lll.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | fmt.Println("Wow! This line is soooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo long...") 7 | } 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/golang_lint/issues/maintidx.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var a int 7 | var b int 8 | var operator string 9 | 10 | fmt.Scan(&a) 11 | fmt.Scan(&b) 12 | fmt.Scan(&operator) 13 | 14 | if operator == "+" { 15 | if a == 0 && b == 0 { 16 | fmt.Print(0) 17 | } else if a == 0 && b == 1 { 18 | fmt.Print(1) 19 | } else if a == 0 && b == 2 { 20 | fmt.Print(2) 21 | } else if a == 1 && b == 0 { 22 | fmt.Print(1) 23 | } else if a == 1 && b == 1 { 24 | fmt.Print(2) 25 | } else if a == 1 && b == 2 { 26 | fmt.Print(3) 27 | } else if a == 2 && b == 0 { 28 | fmt.Print(2) 29 | } else if a == 2 && b == 1 { 30 | fmt.Print(3) 31 | } else if a == 2 && b == 2 { 32 | fmt.Print(4) 33 | } else { 34 | fmt.Print("I don't known :(") 35 | } 36 | } else if operator == "-" { 37 | if a == 0 && b == 0 { 38 | fmt.Print(0) 39 | } else if a == 0 && b == 1 { 40 | fmt.Print(-1) 41 | } else if a == 0 && b == 2 { 42 | fmt.Print(-2) 43 | } else if a == 1 && b == 0 { 44 | fmt.Print(1) 45 | } else if a == 1 && b == 1 { 46 | fmt.Print(0) 47 | } else if a == 1 && b == 2 { 48 | fmt.Print(-1) 49 | } else if a == 2 && b == 0 { 50 | fmt.Print(2) 51 | } else if a == 2 && b == 1 { 52 | fmt.Print(1) 53 | } else if a == 2 && b == 2 { 54 | fmt.Print(0) 55 | } else { 56 | fmt.Print("I don't know :(") 57 | } 58 | } else if operator == "*" { 59 | if a == 0 && b == 0 { 60 | fmt.Print(0) 61 | } else if a == 0 && b == 1 { 62 | fmt.Print(0) 63 | } else if a == 0 && b == 2 { 64 | fmt.Print(0) 65 | } else if a == 1 && b == 0 { 66 | fmt.Print(0) 67 | } else if a == 1 && b == 1 { 68 | fmt.Print(1) 69 | } else if a == 1 && b == 2 { 70 | fmt.Print(2) 71 | } else if a == 2 && b == 0 { 72 | fmt.Print(0) 73 | } else if a == 2 && b == 1 { 74 | fmt.Print(2) 75 | } else if a == 2 && b == 2 { 76 | fmt.Print(4) 77 | } else { 78 | fmt.Print("I don't know :(") 79 | } 80 | } else if operator == "/" { 81 | if a == 0 && b == 0 { 82 | fmt.Print("I don't know :(") 83 | } else if a == 0 && b == 1 { 84 | fmt.Print(0) 85 | } else if a == 0 && b == 2 { 86 | fmt.Print(0) 87 | } else if a == 1 && b == 0 { 88 | fmt.Print("o_0") 89 | } else if a == 1 && b == 1 { 90 | fmt.Print(1) 91 | } else if a == 1 && b == 2 { 92 | fmt.Print(1 / 2) 93 | } else if a == 2 && b == 0 { 94 | fmt.Print(0) 95 | } else if a == 2 && b == 1 { 96 | fmt.Print(2) 97 | } else if a == 2 && b == 2 { 98 | fmt.Print(1) 99 | } else { 100 | fmt.Print("I don't know :(") 101 | } 102 | } else { 103 | fmt.Print("I don't know :(") 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /test/resources/inspectors/golang_lint/multi_file_project_without_issues.json: -------------------------------------------------------------------------------- 1 | { 2 | "Issues": [] 3 | } 4 | -------------------------------------------------------------------------------- /test/resources/inspectors/golang_lint/single_file_project_without_issues.json: -------------------------------------------------------------------------------- 1 | { 2 | "Issues": [] 3 | } 4 | -------------------------------------------------------------------------------- /test/resources/inspectors/intellij_output/test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | file://$PROJECT_DIR$/python_sources/test.py 4 | 8 5 | python_sources 6 | <default> 7 | 8 | Unnecessary parentheses 9 | description_1 10 | 11 | 12 | file://$PROJECT_DIR$/python_sources/test.py 13 | 9 14 | python_sources 15 | <default> 16 | 17 | Overly complex boolean expression 18 | description_2 19 | 20 | 21 | file://$PROJECT_DIR$/python_sources/test.py 22 | 10 23 | python_sources 24 | <default> 25 | 26 | Wrong arguments to call super 27 | description_3 28 | 29 | 30 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_algorithm_with_scanner.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | class Main { 4 | public static void main(String[] args) { 5 | Scanner s = new Scanner(System.in); 6 | int length = s.nextInt(); 7 | int[] nums = new int[length]; 8 | for (int i = 0; i < length; i++) { 9 | nums[i] = s.nextInt(); 10 | } 11 | int limit = s.nextInt(); 12 | int sum = 0; 13 | for (int n : nums) { 14 | if (n > limit) { 15 | sum += n; 16 | } 17 | } 18 | System.out.println(sum); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_array_type.java: -------------------------------------------------------------------------------- 1 | class HelloWorld { 2 | public static void main(String args[]) { 3 | System.out.println("Hello World!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_blocks.java: -------------------------------------------------------------------------------- 1 | class HelloWorld { 2 | public static void main(String[] args) { 3 | try { 4 | System.out.println("Hello World!"); 5 | } catch (Exception e) { 6 | } 7 | 8 | if (0 < 1) int i = 0; 9 | else { int i = 1; } 10 | 11 | for (i = 0; i < 1; i++) 12 | System.out.println("Hello World Again!"); 13 | 14 | { 15 | int i = 1; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_boolean_expr.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | class BooleanExpressions { 4 | 5 | public static void main(String[] args) { 6 | Scanner scanner = new Scanner(System.in); 7 | 8 | int a = scanner.nextInt(); 9 | int b = scanner.nextInt(); 10 | int c = scanner.nextInt(); 11 | int d = scanner.nextInt(); 12 | 13 | if (a > b) { // ok 14 | System.out.println("a > b"); 15 | } 16 | 17 | if (a > b && a > b) { // duplicated 18 | System.out.println("a > b again"); 19 | } 20 | 21 | if (a > b && a < d) { 22 | System.out.println("b < a < d"); 23 | } 24 | 25 | if (a > b && true) { // should be simplified 26 | System.out.println("a > b > c"); 27 | } 28 | 29 | process(a, b, c, d); 30 | } 31 | 32 | private static void process(int a, int b, int c, int d) { 33 | boolean enabled = false; 34 | if (a > b && b < c && c > d || c < a && enabled) { 35 | System.out.println("Too complex"); 36 | } 37 | 38 | for (int i = 0; i < 10; i++) { 39 | System.out.println(getValue(i)); 40 | } 41 | } 42 | 43 | private static boolean getValue(int i) { 44 | if (i < 1) { 45 | return true; 46 | } else { 47 | return false; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_builder.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.List; 3 | import java.util.Scanner; 4 | 5 | class Geek { 6 | 7 | private String type; 8 | private List languages; 9 | private int experience; 10 | 11 | Geek(String type, List languages, int experience) { 12 | this.type = type; 13 | this.languages = languages; 14 | this.experience = experience; 15 | } 16 | 17 | public static class GeekBuilder { 18 | 19 | private String type; 20 | private List languages; 21 | private int experience; 22 | 23 | public GeekBuilder setType(String type) { 24 | this.type = type; 25 | return this; 26 | } 27 | 28 | public GeekBuilder setLanguages(List languages) { 29 | this.languages = languages; 30 | return this; 31 | } 32 | 33 | public GeekBuilder setExperience(int experience) { 34 | this.experience = experience; 35 | return this; 36 | } 37 | 38 | public Geek build() { 39 | return new Geek(type, languages, experience); 40 | } 41 | } 42 | 43 | public String toString() { 44 | return "Type : " + type + "\n" + 45 | "Languages : " + languages + "\n" + 46 | "Experience : " + experience + " years"; 47 | } 48 | } 49 | 50 | class TestDrive { 51 | public static void main(String[] args) { 52 | final Scanner scanner = new Scanner(System.in); 53 | final String geekName = scanner.nextLine(); 54 | scanner.close(); 55 | System.out.println("Geek " + geekName + " created."); 56 | 57 | Geek geek = new Geek.GeekBuilder() 58 | .setType("Admin") 59 | .setLanguages(new ArrayList<>() {{ 60 | add("Perl"); 61 | add("PowerShell"); 62 | }}) 63 | .setExperience(10) 64 | .build(); 65 | 66 | System.out.println(geek); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_class_with_booleans.java: -------------------------------------------------------------------------------- 1 | class ClassWithBooleans { 2 | private boolean enabled = true; 3 | private boolean isTyped = true; 4 | private boolean count = false; 5 | private boolean correct = true; 6 | private int isValid = 1; 7 | 8 | public boolean getEnabled() { 9 | return enabled; 10 | } 11 | 12 | public boolean isTyped() { 13 | return isTyped; 14 | } 15 | 16 | public boolean getCount() { 17 | return count; 18 | } 19 | 20 | public boolean isEnabled() { 21 | return enabled; 22 | } 23 | 24 | public boolean isCount() { 25 | return count; 26 | } 27 | 28 | public boolean isCorrect() { 29 | return correct; 30 | } 31 | 32 | public int getIsValid() { 33 | return isValid; 34 | } 35 | 36 | 37 | public static void main(String[] args) { 38 | ClassWithBooleans object = new ClassWithBooleans(); 39 | System.out.println(object.isTyped()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_closing_streams.java: -------------------------------------------------------------------------------- 1 | import java.io.FileInputStream; 2 | import java.io.IOException; 3 | import java.io.InputStream; 4 | 5 | class TryWithResourcesExample { 6 | private static final String FILE_NAME = "test.java"; 7 | 8 | public static void main(String[] args) { 9 | InputStream in = null; 10 | try { 11 | in = new FileInputStream(FILE_NAME); 12 | System.out.println(in.read()); 13 | } catch (IOException e) { 14 | System.out.println(e.getMessage()); 15 | } finally { 16 | try { 17 | if (in != null) { 18 | in.close(); 19 | } 20 | } catch (IOException ignored) { 21 | // ignored 22 | } 23 | } 24 | 25 | // better use try-with-resources 26 | try (InputStream in2 = new FileInputStream(FILE_NAME)) { 27 | System.out.println(in2.read()); 28 | } catch (IOException e) { 29 | System.out.println(e.getMessage()); 30 | } 31 | 32 | try { 33 | InputStream in3 = new FileInputStream(FILE_NAME); 34 | System.out.println(in3.read()); 35 | } catch (IOException e) { 36 | System.out.print(e.getMessage()); 37 | // it will be good to check closing 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_code_with_comments.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | class CodeWithCommentsExample { 4 | 5 | public static void main(String[] args) { 6 | Scanner scanner = new Scanner(System.in); 7 | 8 | int a = scanner.nextInt(); 9 | a += 20; 10 | // a += 30 11 | // a += 40 12 | System.out.print(a); // good 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_comparing_strings.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | class ComparingStrings { 4 | 5 | public static void main(String[] args) { 6 | Scanner scanner = new Scanner(System.in); 7 | String line = scanner.nextLine(); 8 | 9 | System.out.println(line == "Hello"); 10 | System.out.println(line.equalsIgnoreCase("Hello, World")); 11 | System.out.println(line.equals("World")); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_constants.java: -------------------------------------------------------------------------------- 1 | class MyClass { 2 | static final int log = 10; // OK 3 | static final int logger = 50; // OK 4 | static final int logMYSELF = 10; // violation 5 | static final int loggerMYSELF = 5; // violation 6 | static final int MYSELF = 100; // OK 7 | static final int myselfConstant = 1; // violation 8 | static final long serialVersionUID = 1L; // OK 9 | static final long thingCost = 400L; // violation 10 | } 11 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_covariant_equals.java: -------------------------------------------------------------------------------- 1 | import java.util.Objects; 2 | 3 | class Device { 4 | private String name; 5 | private String model; 6 | 7 | public boolean equals(Device device) { 8 | return Objects.equals(name, device.name) 9 | && Objects.equals(model, device.model); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_curly_braces.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | class HelloWorld { 4 | public static void main(String[] args) { 5 | for (int i = 0; i < args[0].length(); i++) 6 | System.out.println("Hello World!"); 7 | 8 | Scanner scanner = new Scanner(System.in); 9 | int num = scanner.nextInt(); 10 | int counter = 0; 11 | 12 | switch (num) { 13 | case 1: 14 | counter++; 15 | break; // OK 16 | case 6: 17 | counter += 10; 18 | break; // OK 19 | default: 20 | counter = 100; 21 | break; // OK 22 | } 23 | 24 | for (int i = 0; i < 10; i++) System.out.println(i); 25 | 26 | System.out.println(counter); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_double_checked_locking.java: -------------------------------------------------------------------------------- 1 | // Broken multithreaded version 2 | class Helper { 3 | private Helper helper; 4 | 5 | public Helper getHelper() { 6 | if (helper == null) { 7 | synchronized (this) { 8 | if (helper == null) { 9 | helper = new Helper(); 10 | } 11 | } 12 | } 13 | return helper; 14 | } 15 | 16 | // other functions and members... 17 | } 18 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_empty_line_separator.java: -------------------------------------------------------------------------------- 1 | 2 | public class QQMain { 3 | 4 | public static void main(String[] args) { 5 | System.out.println("SADASD"); 6 | } 7 | public static void f() { 8 | System.out.println("ASDS"); 9 | } 10 | } 11 | class Application { 12 | 13 | String name; 14 | 15 | public void run(String[] args) { 16 | System.out.println(name); 17 | 18 | for (String arg : args) { 19 | System.out.println(arg); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_empty_lines_btw_members.java: -------------------------------------------------------------------------------- 1 | class ClassWithMembers { 2 | private static final int LIGHT_SPEED = 3 * 100_000_000; 3 | private static final double PI = 3.1415; 4 | 5 | private final String msg; 6 | private final int cost = 10; 7 | ClassWithMembers(String msg) { 8 | this.msg = msg; 9 | } 10 | public String getMsg() { 11 | return msg; 12 | } 13 | 14 | public int getCost() { 15 | return cost; 16 | } 17 | 18 | public static void main(String[] args) { 19 | ClassWithMembers instance = new ClassWithMembers("Hello"); 20 | System.out.println(instance.getMsg()); 21 | System.out.println(instance.getCost()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_for_loop.java: -------------------------------------------------------------------------------- 1 | import java.util.List; 2 | 3 | class ForLoopExample { 4 | 5 | public static void main(String[] args) { 6 | List numbers = List.of(1, 2, 3, 4, 5); 7 | for (int n : numbers) { 8 | System.out.println(n); 9 | } 10 | 11 | for (int i = 0; i < numbers.size(); i++) { 12 | System.out.println(numbers.get(i)); 13 | } 14 | 15 | for (int i = 0, j = 0, k = 0; i < 10; i++, j++, k++) { 16 | System.out.println(i + j + k); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_implementation_types.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.HashSet; 3 | 4 | class Main { 5 | 6 | public static void main(String[] args) { 7 | ArrayList words = new ArrayList<>(); 8 | 9 | words.add("first"); 10 | words.add("second"); 11 | words.add("third"); 12 | 13 | System.out.println(words); 14 | 15 | HashSet uniqueNumbers = new HashSet<>(); 16 | 17 | uniqueNumbers.add(1); 18 | uniqueNumbers.add(2); 19 | uniqueNumbers.add(3); 20 | 21 | System.out.println(uniqueNumbers); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_indentation_google_style.java: -------------------------------------------------------------------------------- 1 | // See here https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml 2 | public class AndroidIndentation { 3 | public static void main(String[] args) { 4 | int a = 10; 5 | int b = 20; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_indentation_with_spaces.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.List; 3 | 4 | class Indentation { 5 | 6 | public static void main(String[] args) { 7 | int a = 10; 8 | int b = 20; 9 | 10 | System.out.println(a + b); 11 | 12 | var words = List.of( 13 | "Hello", 14 | "How is it going?", 15 | "Let's program!" 16 | ); 17 | 18 | var numbers = Arrays.asList( 19 | 100, 20 | 200, 21 | 300 22 | ); 23 | 24 | invokeMethod(words, numbers); 25 | } 26 | 27 | private static void invokeMethod(List words, 28 | List numbers) { 29 | 30 | System.out.println(words); 31 | System.out.println(numbers); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_indentation_with_tabs.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.List; 3 | 4 | class Indentation { 5 | 6 | public static void main(String[] args) { 7 | int a = 10; 8 | int b = 20; 9 | 10 | System.out.println(a + b); 11 | 12 | var words = List.of( 13 | "Hello", 14 | "How is it going?", 15 | "Let's program!" 16 | ); 17 | 18 | var numbers = Arrays.asList( 19 | 100, 20 | 200, 21 | 300 22 | ); 23 | 24 | invokeMethod(words, numbers); 25 | } 26 | 27 | private static void invokeMethod(List words, 28 | List numbers) { 29 | 30 | System.out.println(words); 31 | System.out.println(numbers); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_invalid_naming.java: -------------------------------------------------------------------------------- 1 | class snake_class { 2 | private static final String text = ""; 3 | private static final String anotherText = ""; 4 | 5 | private String snake_field; 6 | private String CAPS_FIELD; 7 | 8 | public static void Main(String[] ARGS) { 9 | int CAPS_VAR; 10 | int snake_var; 11 | } 12 | 13 | private void snake_method(int snake_arg, int CAPS_ARG) { 14 | } 15 | 16 | private void CAPS() { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_long_lines.java: -------------------------------------------------------------------------------- 1 | class Main { 2 | 3 | public static void main(String[] args) { 4 | System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); 5 | System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); 6 | System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_magic_numbers.java: -------------------------------------------------------------------------------- 1 | class HelloWorld { 2 | private static final int VALUE = 123; 3 | 4 | public static void main(String[] args) { 5 | int i = 123; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_manual_array_copy.java: -------------------------------------------------------------------------------- 1 | class Main { 2 | public static void main(String[] args) { 3 | String[] another = new String[args.length]; 4 | for (int i = 0; i < args.length; i++) { 5 | another[i] = args[i]; 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_method_params.java: -------------------------------------------------------------------------------- 1 | class MethodsParametersExample { 2 | 3 | public static void main(String[] args) { 4 | message("Vasiliy", "Anna", 5 | "anna@gmail.com", 6 | "Hello!", "How are u?"); 7 | System.out.println(calculate(10, 12, 15)); 8 | } 9 | 10 | public static void message(String from, String to, String email, 11 | String header, String text) { 12 | System.out.printf("Sending from '%s' to '%s' on email '%s' " + 13 | "with header '%s' and text '%s'", 14 | from, to, email, header, text); 15 | } 16 | 17 | private static int calculate(int a, int b, int c) { 18 | return a + b; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_missing_default.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | class HelloWorld { 4 | public static void main(String[] args) { 5 | Scanner scanner = new Scanner(System.in); 6 | int x = 1; 7 | int y = scanner.nextInt(); 8 | switch (x) { 9 | case 0: 10 | y = 1; 11 | break; 12 | } 13 | System.out.println(x); 14 | System.out.println(y); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_multi_statements.java: -------------------------------------------------------------------------------- 1 | class MultistatementsPerLineExample { 2 | 3 | public static void main(String[] args) { 4 | int a = 10, b = 20; 5 | int c = 30; int result = a + b + c; 6 | System.out.println(c); System.out.println(result); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_multiple_literals.java: -------------------------------------------------------------------------------- 1 | class Main { 2 | public static void main(String[] args) { 3 | // ok 4 | String shortRareLiteral1 = "12"; 5 | String shortRareLiteral2 = "12"; 6 | String shortRareLiteral3 = "12"; 7 | 8 | // ok 9 | String longRareLiteral1 = "123"; 10 | String longRareLiteral2 = "123"; 11 | String longRareLiteral3 = "123"; 12 | 13 | // ok 14 | String shortFrequentLiteral1 = "34"; 15 | String shortFrequentLiteral2 = "34"; 16 | String shortFrequentLiteral3 = "34"; 17 | String shortFrequentLiteral4 = "34"; 18 | 19 | // warning 20 | String longFrequentLiteral1 = "456"; 21 | String longFrequentLiteral2 = "456"; 22 | String longFrequentLiteral3 = "456"; 23 | String longFrequentLiteral4 = "456"; 24 | 25 | System.out.println( 26 | shortRareLiteral1 + shortRareLiteral2 + shortRareLiteral3 + 27 | longRareLiteral1 + longRareLiteral2 + longRareLiteral3 + 28 | shortFrequentLiteral1 + shortFrequentLiteral2 + shortFrequentLiteral3 + shortFrequentLiteral4 + 29 | longFrequentLiteral1 + longFrequentLiteral2 + longFrequentLiteral3 + longFrequentLiteral4 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_nested_blocks.java: -------------------------------------------------------------------------------- 1 | class NestedBlocksExample { 2 | public static void main(String[] args) { 3 | int a = 10; 4 | { 5 | a = 20; 6 | System.out.println(a); 7 | } 8 | switch (a) { 9 | case 0: 10 | x = 1; 11 | break; 12 | case 1: 13 | // Never OK, statement outside block 14 | System.out.println("Hello 1"); 15 | { 16 | x = 2; 17 | break; 18 | } 19 | case 2: { 20 | // OK if allowInSwitchCase is true 21 | System.out.println("Hello 2"); 22 | x = 3; 23 | break; 24 | } 25 | default: { 26 | System.out.println("Unknown case"); 27 | break; 28 | } 29 | } 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_pattern_matching.java: -------------------------------------------------------------------------------- 1 | class Main { 2 | public static void main(String[] args) 3 | { 4 | Object obj = "TEST"; 5 | 6 | if (obj instanceof String t) { 7 | System.out.println((t)); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_reassigning_example.java: -------------------------------------------------------------------------------- 1 | class ReassigningExample { 2 | 3 | public static void main(String[] args) { 4 | for (int i = 0, j = 0; i < 10; i++, j++) { 5 | i++; 6 | System.out.println(sum(i, j)); 7 | } 8 | } 9 | 10 | private static int sum(int a, int b) { 11 | a = 10; 12 | return a + b; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_records.java: -------------------------------------------------------------------------------- 1 | record Book(String title, String author, String isbn) { } 2 | 3 | class OuterClass { 4 | class InnerClass { 5 | Book book = new Book("Title", "author", "isbn"); 6 | } 7 | } 8 | 9 | class Main { 10 | public static void main(String[] args) 11 | { 12 | OuterClass.InnerClass a = new OuterClass.InnerClass(); 13 | System.out.println((a.book)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_sealed_classes.java: -------------------------------------------------------------------------------- 1 | package main; 2 | 3 | public sealed class Figure { } 4 | 5 | final class Circle extends Figure { 6 | float radius; 7 | } 8 | non-sealed class Square extends Figure { 9 | float side; 10 | } 11 | sealed class Rectangle extends Figure { 12 | float length, width; 13 | } 14 | final class FilledRectangle extends Rectangle { 15 | int red, green, blue; 16 | } 17 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_simple_valid_program.java: -------------------------------------------------------------------------------- 1 | class Main { 2 | public static void main(String[] args) { 3 | System.out.println("Hello World!"); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_spaces.java: -------------------------------------------------------------------------------- 1 | class HelloWorld { 2 | public static void main( String[] args) { 3 | int j=0+1; 4 | for( int i = 0; i System.out.println("Hello!")); 5 | t.run(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_todo.java: -------------------------------------------------------------------------------- 1 | class HelloWorld { 2 | //TODO: 3 | public static void main(String[] args) { 4 | // TODO: stub 5 | System.out.println("Hello World!"); 6 | 7 | // TODO: 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_unused_imports.java: -------------------------------------------------------------------------------- 1 | import java.utils.*; // valid 2 | import java.util.List; 3 | import java.lang.String; 4 | import java.util.List; 5 | 6 | class HelloWorld { 7 | public static void main(String[] args) { 8 | System.out.println("Hello World!"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_upper_ell.java: -------------------------------------------------------------------------------- 1 | class HelloWorld { 2 | public static void main(String[] args) { 3 | long x = 1l; 4 | long y = 1L; 5 | System.out.println(x + y); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_valid_algorithm_1.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class Main { 4 | public static void main(String[] args) { 5 | // write your code here 6 | Scanner scanner = new Scanner(System.in); 7 | int heightBus = scanner.nextInt(); 8 | int bridges = scanner.nextInt(); 9 | scanner.nextLine(); 10 | String heightBridges = scanner.nextLine(); 11 | String[] heightsList = heightBridges.split(" "); 12 | String willNotCrash = "Will not crash"; 13 | String willCrash = ""; 14 | 15 | for (int i = 0; i < bridges; i++) { 16 | if (heightBus >= Integer.parseInt(heightsList[i])) { 17 | willCrash = "Will crash on bridge " + (i + 1); 18 | break; 19 | } 20 | } 21 | 22 | if ("".equals(willCrash)) { 23 | System.out.println(willNotCrash); 24 | } else { 25 | System.out.println(willCrash); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_valid_blocks.java: -------------------------------------------------------------------------------- 1 | class HelloWorld { 2 | public static void main(String[] args) { 3 | try { 4 | System.out.println("Hello World!"); 5 | } catch (Exception e) { 6 | // ignored 7 | } 8 | 9 | if (0 < 1) { 10 | int i = 0; 11 | } else { 12 | int i = 1; 13 | } 14 | 15 | for (i = 0; i < 1; i++) { 16 | System.out.println("Hello World Again!"); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_valid_curly_braces.java: -------------------------------------------------------------------------------- 1 | class HelloWorld { 2 | public static void main(String[] args) { 3 | for (int i = 0; i < args[0].length(); i++) { 4 | if (i < 1) { 5 | System.out.println("Hello World!"); 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_valid_default.java: -------------------------------------------------------------------------------- 1 | class HelloWorld { 2 | public static void main(String[] args) { 3 | int x = 1; 4 | int y; 5 | switch (x) { 6 | case 0: 7 | y = 1; 8 | break; 9 | default: 10 | y = 0; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_valid_naming.java: -------------------------------------------------------------------------------- 1 | class MyClass { 2 | private static final String NAME = ""; 3 | private static final String ANOTHER_NAME = ""; 4 | 5 | private String field; 6 | private String anotherField; 7 | 8 | public static void main(String[] args) { 9 | int value = 0; 10 | } 11 | 12 | private void foo() { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_valid_spaces.java: -------------------------------------------------------------------------------- 1 | class HelloWorld { 2 | public static void main(String[] args) { 3 | int j = 1; 4 | for (int i = 0; i < j; i++) { 5 | System.out.println("Hello World!"); 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/resources/inspectors/java/test_when_only_equals_overridden.java: -------------------------------------------------------------------------------- 1 | import java.util.Objects; 2 | 3 | class Person { 4 | 5 | private String firstName; 6 | private String lastName; 7 | private int age; 8 | 9 | // constructor, getters and setters 10 | 11 | @Override 12 | public boolean equals(Object other) { 13 | /* Check this and other refer to the same object */ 14 | if (this == other) { 15 | return true; 16 | } 17 | 18 | /* Check other is Person and not null */ 19 | if (!(other instanceof Person)) { 20 | return false; 21 | } 22 | 23 | Person person = (Person) other; 24 | 25 | /* Compare all required fields */ 26 | return age == person.age && 27 | Objects.equals(firstName, person.firstName) && 28 | Objects.equals(lastName, person.lastName); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/resources/inspectors/js/case0_no_issues.js: -------------------------------------------------------------------------------- 1 | function sum(a, b) { 2 | return a + b; 3 | } 4 | 5 | console.log(sum(5, 6)); 6 | -------------------------------------------------------------------------------- /test/resources/inspectors/js/case1_with_issues.js: -------------------------------------------------------------------------------- 1 | function a(x) { 2 | var b = 10; 3 | if (true) { 4 | return x; 5 | } else if (false) { 6 | return x+1; 7 | } else { 8 | return 4; 9 | } 10 | } 11 | 12 | function sayHello(name){ 13 | alert("Hello " + name); 14 | } 15 | 16 | name = "Douglas Crockford"; 17 | sayHello(name) 18 | -------------------------------------------------------------------------------- /test/resources/inspectors/js/case2_semi_node_and_unused.js: -------------------------------------------------------------------------------- 1 | var qqq = 10; 2 | 3 | var readline = require('readline') 4 | var rl = readline.createInterface({ 5 | input: process.stdin, 6 | output: process.stdout 7 | }); 8 | 9 | rl.on('line', (line) => { 10 | let arr = []; 11 | if (line.trim() !== '') { 12 | arr = line.split(' ').map((n) => parseInt(n, 10)); 13 | } 14 | 15 | console.log(sum(arr[0], arr[1])); 16 | }); 17 | 18 | function sum(a, b) { 19 | return a + b; 20 | } 21 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case0_good_program.kt: -------------------------------------------------------------------------------- 1 | import java.util.Scanner 2 | 3 | fun main() { 4 | val scanner = Scanner(System.`in`) 5 | 6 | val a = scanner.nextInt() 7 | val b = scanner.nextInt() 8 | 9 | println(a + b) 10 | } 11 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case10_long_lines.kt: -------------------------------------------------------------------------------- 1 | import java.util.Scanner 2 | 3 | class Person(id: Int, firstName: String, lastName: String, middleName: String?, age: Int, email: String?, phoneNumber: String?, twitterHandle: String?) 4 | 5 | fun main() { 6 | val scanner = Scanner(System.`in`) 7 | 8 | val n = scanner.nextInt() // sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss 9 | print(n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n + n) 10 | } 11 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case11_bad_ident.kt: -------------------------------------------------------------------------------- 1 | 2 | import java.util.Scanner 3 | 4 | fun main() { 5 | val scanner = Scanner(System.`in`) 6 | val n = scanner.nextInt() 7 | println(n) 8 | } 9 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case12_bad_filename.kt: -------------------------------------------------------------------------------- 1 | open class MotorVehicle 2 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case13_good_filename.kt: -------------------------------------------------------------------------------- 1 | open class MotorVehicle 2 | 3 | class Car : MotorVehicle() 4 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case14_keyword_spacing.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | if(true) { 3 | println(1) 4 | } 5 | while(true) { 6 | println(1) 7 | } 8 | do { 9 | println(1) 10 | } while(true) 11 | if (true) { 12 | println(1) 13 | } else { 14 | println(1) 15 | } 16 | } 17 | 18 | fun foo1() { 19 | try { "".trim() } 20 | catch (e: Exception) { 21 | println(1) 22 | } 23 | finally { 24 | println(1) 25 | } 26 | if (true) { 27 | } else { 28 | println(1) 29 | } 30 | if (true) { println(1) } else { println(1) } 31 | if (true) 32 | println() 33 | else 34 | entry.value 35 | } 36 | 37 | fun foo2() { 38 | try { 39 | "".trim() 40 | } catch (e: Exception) { 41 | } finally { println(1) } 42 | try { "".trim() } catch (e: Exception) { println(1) } finally { println(1) } 43 | val v = 0 44 | when (v) { 45 | 1 -> println("") 46 | else -> println("") 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case15_empty_class_func.kt: -------------------------------------------------------------------------------- 1 | class Nothing { } 2 | 3 | fun no() { } 4 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case16_redundant_unit.kt: -------------------------------------------------------------------------------- 1 | fun printHello(): Unit { 2 | println("Hello!") 3 | } 4 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case17_modifier_order.kt: -------------------------------------------------------------------------------- 1 | private final data class Nothing1(val field: Int) 2 | 3 | final data class Nothing2(val field: Int) 4 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case18_redundant_braces.kt: -------------------------------------------------------------------------------- 1 | 2 | fun main() { 3 | val minutes = 30 4 | val sec = 40 5 | val ms = 200 6 | 7 | println("Time taken ${minutes} min. ${sec} sec. ${ms} ms.") 8 | } 9 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case19_private_property.kt: -------------------------------------------------------------------------------- 1 | 2 | import java.util.* 3 | 4 | class ConsoleHelper(val scanner: Scanner) { 5 | 6 | fun print(msg: String = "") = println(msg) 7 | 8 | fun askLine(msg: String = ""): String { 9 | if (msg != "") this.print(msg) 10 | return scanner.nextLine() 11 | } 12 | 13 | fun askInt(msg: String = ""): Int { 14 | if (msg != "") this.print(msg) 15 | return scanner.nextInt() 16 | } 17 | 18 | fun askDouble(msg: String = ""): Double { 19 | if (msg != "") this.print(msg) 20 | return scanner.nextDouble() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case1_coffee_machine.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | println("Starting to make a coffee") 3 | println("Grinding coffee beans") 4 | println("Boiling water") 5 | println("Mixing boiled water with crushed coffee beans") 6 | println("Pouring coffee into the cup") 7 | println("Pouring some milk into the cup") 8 | println("Coffee is ready!") 9 | } 10 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case20_cyclomatic_complexity.kt: -------------------------------------------------------------------------------- 1 | import java.util.Scanner 2 | 3 | class Main { 4 | val yes = "YES" 5 | val no = "NO" 6 | 7 | fun main() { 8 | printArmy() 9 | checkTriangle() 10 | checkQueens() 11 | calculator() 12 | } 13 | 14 | // CC is 10 15 | fun printArmy() { 16 | val scanner = Scanner(System.`in`) 17 | val p = scanner.nextInt() 18 | if (p < 1) { 19 | println("no army") 20 | } else if (p < 5) { 21 | println("few") 22 | } else if (p < 10) { 23 | println("several") 24 | } else if (p < 20) { 25 | println("pack") 26 | } else if (p < 50) { 27 | println("lots") 28 | } else if (p < 100) { 29 | println("horde") 30 | } else if (p < 250) { 31 | println("throng") 32 | } else if (p < 500) { 33 | println("swarm") 34 | } else if (p < 1000) { 35 | println("zounds") 36 | } else { 37 | println("legion") 38 | } 39 | } 40 | 41 | fun checkTriangle() { // CC is 4 42 | val scanner = Scanner(System.`in`) 43 | 44 | val a = scanner.nextInt() 45 | val b = scanner.nextInt() 46 | val c = scanner.nextInt() 47 | 48 | if (a + b > c && b + c > a && c + a > b) { 49 | println(yes) 50 | } else { 51 | println(no) 52 | } 53 | } 54 | 55 | fun checkQueens() { // CC is 4 56 | val scanner = Scanner(System.`in`) 57 | 58 | val num1 = scanner.nextInt() 59 | val num2 = scanner.nextInt() 60 | val num3 = scanner.nextInt() 61 | val num4 = scanner.nextInt() 62 | 63 | if (num1 == num3) { 64 | println(yes) 65 | } else if (num2 == num4) { 66 | println(yes) 67 | } else if (Math.abs(num1 - num3) == Math.abs(num2 - num4)) { 68 | println(NO) 69 | } else { 70 | println(no) 71 | } 72 | } 73 | 74 | fun calculator() { // CC is 3 75 | val scanner = Scanner(System.`in`) 76 | 77 | val line = scanner.nextLine().split("\\s+") 78 | 79 | val a = Long.parseLong(line[0]) 80 | val op = line[1].charAt(0) 81 | val b = Long.parseLong(line[2]) 82 | 83 | when (op) { 84 | '+' -> println(a + b) 85 | '-' -> println(a - b) 86 | '*' -> println(a * b) 87 | '/' -> { 88 | if (b == 0) { 89 | println("Division by 0!") 90 | } else { 91 | println(a / b) 92 | } 93 | else -> println("Unknown operator") 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case21_cyclomatic_complexity_bad.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | if (true) { 3 | println(1) 4 | } 5 | while (true) { 6 | println(1) 7 | } 8 | do { 9 | println(1) 10 | } while (true) 11 | if (true) { 12 | println(1) 13 | } else { 14 | println(1) 15 | } 16 | try { 17 | "".trim() 18 | } catch (e: Exception) { 19 | println(1) 20 | } finally { 21 | println(1) 22 | } 23 | if (true) { 24 | println(1) 25 | } else { 26 | println(1) 27 | } 28 | if (true) { 29 | println(1) 30 | } else { 31 | println(1) 32 | } 33 | if (true) { 34 | println(1) 35 | } else { 36 | println(1) 37 | } 38 | if (true) { 39 | println(1) 40 | } else { 41 | println(1) 42 | } 43 | if (true) { 44 | println() 45 | } else { 46 | entry.value 47 | } 48 | try { 49 | "".trim() 50 | } catch (e: Exception) { 51 | println(1) 52 | } finally { 53 | println(1) 54 | } 55 | try { 56 | "".trim() 57 | } catch (e: Exception) { 58 | println(1) 59 | } finally { 60 | println(1) 61 | } 62 | val v = 0 63 | if (v == 1) { 64 | println("") 65 | } else { 66 | println("") 67 | } 68 | if (v) { 69 | v.let { "" } 70 | } else { 71 | v 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case22_too_many_arguments.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | class ConsoleHelper(val scanner: Scanner) { 4 | // 6+ -- is bad 5 | fun askLine( 6 | msg1: String = "", 7 | msg1: String = "", 8 | msg1: String = "", 9 | msg1: String = "", 10 | msg1: String = "", 11 | msg1: String = "" 12 | ): String { 13 | if (msg != "") { 14 | this.print(msg) 15 | } 16 | return scanner.nextLine() 17 | } 18 | 19 | // < 6 -- is ok 20 | fun askLine2( 21 | msg1: String = "", 22 | msg1: String = "", 23 | msg1: String = "", 24 | msg1: String = "", 25 | msg1: String = "" 26 | ): String { 27 | if (msg != "") { 28 | this.print(msg) 29 | } 30 | return scanner.nextLine() 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case23_bad_range_performance.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | // bad 3 | (1..10).forEach { 4 | println(it) 5 | } 6 | (1 until 10).forEach { 7 | println(it) 8 | } 9 | (10 downTo 1).forEach { 10 | println(it) 11 | } 12 | 13 | // ok 14 | for (i in 1..10) { 15 | println(i) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case24_duplicate_when_bug.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | // bad 3 | when (i) { 4 | 1 -> println("one") 5 | 1 -> println("one") 6 | else -> println("else") 7 | } 8 | 9 | // ok 10 | when (i) { 11 | 1 -> println("one") 12 | 2 -> println("two") 13 | else -> println("else") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case25_unreachable_code.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | for (i in 1..2) { 3 | break 4 | println() // unreachable 5 | } 6 | 7 | throw IllegalArgumentException("message") 8 | println() // unreachable 9 | 10 | fun f() { 11 | return 12 | println() // unreachable 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case26_var_could_be_val.kt: -------------------------------------------------------------------------------- 1 | fun example() { 2 | var i = 1 // violation: this variable is never re-assigned 3 | val j = i + 1 4 | } 5 | 6 | // ok 7 | fun example() { 8 | val i = 1 9 | val j = i + 1 10 | 11 | } 12 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case2_valid_program.kt: -------------------------------------------------------------------------------- 1 | fun main() { 2 | println("Hello World!") 3 | 4 | val message = "Hello World!" 5 | println(message) 6 | } 7 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case3_todo.kt: -------------------------------------------------------------------------------- 1 | // TODO: stub 2 | fun main() { 3 | // TODO: stub 4 | println("Hello World!") 5 | // TODO: stub 6 | } 7 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case4_semicolons.kt: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | fun main() { 4 | val scanner = Scanner(System.`in`); 5 | 6 | val a = scanner.nextInt(); 7 | val b = scanner.nextInt(); 8 | 9 | println(a + b); 10 | }; 11 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case5_imports.kt: -------------------------------------------------------------------------------- 1 | import java.* // bad 2 | import java.util.* 3 | import java.time.LocalDate 4 | import java.util.Scanner 5 | import java.time.LocalDate 6 | import java.util.BitSet 7 | 8 | fun main() { 9 | val scanner = Scanner(System.`in`) 10 | val date = LocalDate.of(2020, 10, 10) 11 | println(date) 12 | } 13 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case6_missing_spaces.kt: -------------------------------------------------------------------------------- 1 | import java.util.Scanner 2 | 3 | fun main() { 4 | val scanner = Scanner(System.`in`) 5 | 6 | val a: Int = scanner.nextInt() 7 | val b:Int = scanner.nextInt() 8 | val c : Int = scanner.nextInt() 9 | 10 | //some operations below 11 | println(a+b) 12 | println(a- b) 13 | println("${a *b} ml of water") 14 | 15 | val q: Int ? = null // should be space 16 | } 17 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case7_immutability.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | fun main() { 4 | var scanner = Scanner(System.`in`) 5 | var n = scanner.nextInt() 6 | println(n) 7 | } 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case8_needless_blank_line.kt: -------------------------------------------------------------------------------- 1 | import java.util.Scanner 2 | 3 | fun main() { 4 | val scanner = Scanner(System.`in`) 5 | 6 | 7 | val n = scanner.nextInt() 8 | 9 | 10 | 11 | println(n) 12 | } 13 | 14 | 15 | 16 | fun first(): Int { 17 | return 0 18 | } 19 | 20 | fun second(): Int { 21 | return 1 22 | } 23 | -------------------------------------------------------------------------------- /test/resources/inspectors/kotlin/case9_braces.kt: -------------------------------------------------------------------------------- 1 | import java.util.Scanner 2 | 3 | fun main() { 4 | val scanner = Scanner(System.`in`) 5 | 6 | val n = scanner.nextInt() 7 | if (n == 10) 8 | { 9 | println("abc") 10 | } 11 | } 12 | 13 | fun main(){ 14 | val scanner = Scanner(System.`in`) 15 | val n = scanner.nextInt() 16 | println(n)} 17 | -------------------------------------------------------------------------------- /test/resources/inspectors/pmd/empty_file.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperskill/hyperstyle/130f96ec5b92873de7e844db4ce09791ff531b41/test/resources/inspectors/pmd/empty_file.csv -------------------------------------------------------------------------------- /test/resources/inspectors/pmd/multi_file_project.csv: -------------------------------------------------------------------------------- 1 | "Problem","Package","File","Priority","Line","Description","Rule set","Rule" 2 | "1","","/home/user/Desktop/some_project/main1.java","3","37","Use equals() to compare object references.","Error Prone","CompareObjectsWithEquals" 3 | "2","","/home/user/Desktop/some_project/main1.java","2","68","The method name and parameter number are suspiciously close to equals(Object)","Error Prone","SuspiciousEqualsMethodName" 4 | "3","","/home/user/Desktop/some_project/main2.java","4","113","Useless parentheses.","Code Style","UselessParentheses" 5 | "4","","/home/user/Desktop/some_project/main2.java","3","131","Avoid empty if statements","Error Prone","EmptyIfStmt" 6 | -------------------------------------------------------------------------------- /test/resources/inspectors/pmd/project_without_issues.csv: -------------------------------------------------------------------------------- 1 | "Problem","Package","File","Priority","Line","Description","Rule set","Rule" 2 | -------------------------------------------------------------------------------- /test/resources/inspectors/pmd/single_file_project.csv: -------------------------------------------------------------------------------- 1 | "Problem","Package","File","Priority","Line","Description","Rule set","Rule" 2 | "1","","/home/user/Desktop/some_project/main.java","3","6","The String literal 'Howdy' appears 4 times in this file; the first occurrence is on line 6","Error Prone","AvoidDuplicateLiterals" 3 | "2","","/home/user/Desktop/some_project/main.java","3","12","Document empty method body","Documentation","UncommentedEmptyMethodBody" 4 | "3","","/home/user/Desktop/some_project/main.java","3","31","Avoid unused local variables such as 'result'.","Best Practices","UnusedLocalVariable" 5 | "4","","/home/user/Desktop/some_project/main.java","3","61","Avoid unused private methods such as 'emptyLoop()'.","Best Practices","UnusedPrivateMethod" -------------------------------------------------------------------------------- /test/resources/inspectors/pylint/issues/r1721.py: -------------------------------------------------------------------------------- 1 | a = [1, 2, 3] 2 | print([elem for elem in a]) 3 | -------------------------------------------------------------------------------- /test/resources/inspectors/pylint/issues/w1404.py: -------------------------------------------------------------------------------- 1 | a = "Hello, " "world!" 2 | print(a) 3 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case0_folder_without_init/hello.py: -------------------------------------------------------------------------------- 1 | if __name__ == '__main__': 2 | print('hello world!') 3 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case0_spaces.py: -------------------------------------------------------------------------------- 1 | a, b, c = (input(),input(),input()) 2 | print(f'{a} {b} {c}') 3 | 4 | print('1', '2', '3', sep = '|') 5 | 6 | result = int(a)+10 7 | print(result) 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case10_unused_variable_in_loop.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def package_files(directory): 5 | paths = [] 6 | for (path, directories, filenames) in os.walk(directory): 7 | for filename in filenames: 8 | paths.append(os.path.join('..', path, filename)) 9 | return paths 10 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case11_redundant_parentheses.py: -------------------------------------------------------------------------------- 1 | nuts = int(input()) 2 | 3 | if (nuts > 10): 4 | print('There is enough nuts') 5 | else: 6 | print('Not enough nuts') 7 | 8 | i = 1 9 | while (i <= nuts): 10 | print(f'Give the nuth №{i}') 11 | i += 1 12 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case12_unreachable_code.py: -------------------------------------------------------------------------------- 1 | def calc_sum(x, y): 2 | return x + y 3 | return x * y 4 | 5 | 6 | for i in range(10): 7 | print(i) 8 | continue 9 | print(i + i) 10 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case13_complex_logic_2.py: -------------------------------------------------------------------------------- 1 | elements = list(input('Enter cells: ')) 2 | y = 0 3 | o = 0 4 | 5 | CROSS_SYMBOL = 'X' 6 | NOUGHT_SYMBOL = 'O' 7 | 8 | for x in elements: 9 | if x == CROSS_SYMBOL: 10 | y = y + 1 11 | elif x == NOUGHT_SYMBOL: 12 | o = o + 1 13 | 14 | odds = abs(y - o) 15 | 16 | up_row = [elements[0], elements[1], elements[2]] 17 | mid_row = [elements[3], elements[4], elements[5]] 18 | down_row = [elements[6], elements[7], elements[8]] 19 | 20 | up_col = [elements[0], elements[3], elements[6]] 21 | mid_col = [elements[1], elements[4], elements[7]] 22 | down_col = [elements[2], elements[5], elements[8]] 23 | 24 | diagonal_1 = [elements[0], elements[4], elements[8]] 25 | diagonal_2 = [elements[2], elements[4], elements[6]] 26 | 27 | full_field = [up_row, up_col, mid_row, mid_col, down_row, down_col, diagonal_1, diagonal_2] 28 | 29 | x_win = [CROSS_SYMBOL, CROSS_SYMBOL, CROSS_SYMBOL] 30 | o_win = [NOUGHT_SYMBOL, NOUGHT_SYMBOL, NOUGHT_SYMBOL] 31 | 32 | field = f""" 33 | --------- 34 | | {elements[0]} {elements[1]} {elements[2]} | 35 | | {elements[3]} {elements[4]} {elements[5]} | 36 | | {elements[6]} {elements[7]} {elements[8]} | 37 | --------- 38 | """ 39 | if odds < 2: 40 | if x_win in full_field and o_win not in full_field: 41 | print(field) 42 | print(f'{CROSS_SYMBOL} wins') 43 | elif o_win in full_field and x_win not in full_field: 44 | print(field) 45 | print(f'{NOUGHT_SYMBOL} wins') 46 | elif o_win in full_field and x_win in full_field: 47 | print(field) 48 | print('Impossible') 49 | elif '_' not in elements: 50 | if o_win not in full_field and x_win not in full_field: 51 | print(field) 52 | print('Draw') 53 | elif '_' in elements: 54 | if o_win not in full_field and x_win not in full_field: 55 | print(field) 56 | print('Game not finished') 57 | elif odds >= 2: 58 | print(field) 59 | print('Impossible') 60 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case14_returns_errors.py: -------------------------------------------------------------------------------- 1 | def f_1(y): 2 | if not y: 3 | return 4 | return None # error! 5 | 6 | 7 | def f_2(y): 8 | if not y: 9 | return # error! 10 | return 1 11 | 12 | 13 | def f_3(y): 14 | if not y: 15 | return # error! 16 | return 1 17 | 18 | 19 | def f_4(): 20 | a = 1 21 | # some code that not using `a` 22 | print('test') 23 | return a # error! 24 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case15_redefining.py: -------------------------------------------------------------------------------- 1 | def grade(score, max_score): 2 | return score * 100 / max_score 3 | 4 | 5 | score = int(input()) 6 | max_score = int(input()) 7 | 8 | grade(score, max_score) 9 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case16_comments.py: -------------------------------------------------------------------------------- 1 | n = int(input()) 2 | 3 | # n += 20 4 | n += 10 5 | 6 | print(n) # ok 7 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case17_dangerous_default_value.py: -------------------------------------------------------------------------------- 1 | def some_fun(a=[]): 2 | a.append('h') 3 | print(a) 4 | 5 | 6 | some_fun([1, 2, 3]) 7 | some_fun([1, 2, 3, 4]) 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case18_comprehensions.py: -------------------------------------------------------------------------------- 1 | numbers = [0 for _ in range(10)] 2 | 3 | list(n + 1 for n in numbers) 4 | set(n + 1 for n in numbers) 5 | 6 | set([n + 1 for n in numbers]) 7 | dict([(n, n * n) for n in numbers]) 8 | 9 | tuple([1, 2]) # (1, 2) 10 | tuple([]) # () 11 | 12 | dict(((1, 2),)) # {1: 2} 13 | 14 | sum([x ** 2 for x in range(10)]) # we allow this since flake8-comprehension 3.4.0 (see its changelog) 15 | 16 | test_dict = dict() # we allow this 17 | test_list = list() # we allow this 18 | test_tuple = tuple() # we allow this 19 | 20 | list([0 for _ in range(10)]) 21 | 22 | reversed(sorted([2, 3, 1])) # sorted([2, 3, 1], reverse=True) 23 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case19_bad_indentation.py: -------------------------------------------------------------------------------- 1 | 2 | def is_even(number): 3 | return number % 2 == 0 4 | 5 | 6 | n = int(input()) 7 | for i in range(n): 8 | print(i) 9 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case1_simple_valid_program.py: -------------------------------------------------------------------------------- 1 | days = int(input()) 2 | 3 | cost_food_per_day = int(input()) 4 | cost_flight = int(input()) 5 | cost_night = int(input()) 6 | 7 | nights = days - 1 8 | total_cost = days * cost_food_per_day + cost_night * nights + cost_flight * 2 9 | 10 | print(total_cost) 11 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case20_imports_order.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | import functools 3 | 4 | from pylint import graph, exceptions 5 | 6 | print(itertools.__name__) 7 | print(functools.__name__) 8 | print(graph, exceptions) 9 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case21_imports.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | import functools 3 | from math import ceil 4 | 5 | print(ceil(0.1)) -------------------------------------------------------------------------------- /test/resources/inspectors/python/case22_reassigning.py: -------------------------------------------------------------------------------- 1 | def fun(greeting): 2 | greeting = 'hello' 3 | print(greeting) 4 | 5 | 6 | for i in range(20): 7 | i += 1 8 | print(i) 9 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case23_merging_comparisons.py: -------------------------------------------------------------------------------- 1 | elements = input() 2 | 3 | row1 = elements[:3] 4 | row2 = elements[3:6] 5 | row3 = elements[6:] 6 | 7 | CROSS = 'X' * 3 8 | ZERO = 'O' * 3 9 | 10 | row_with_x = row1 == CROSS or row2 == CROSS or row3 == CROSS 11 | row_with_o = row1 == ZERO or row2 == ZERO or row3 == ZERO 12 | 13 | if row1 == CROSS or row2 == CROSS or row3 == CROSS: 14 | print('X wins') 15 | 16 | if CROSS == row1 or CROSS == row2: 17 | print('X wins') 18 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case24_long_function.py: -------------------------------------------------------------------------------- 1 | def print_letters(): 2 | print('a') 3 | print('b') 4 | print('c') 5 | print('d') 6 | print('e') 7 | print('f') 8 | print('g') 9 | print('a') 10 | print('b') 11 | print('c') 12 | print('d') 13 | print('e') 14 | print('f') 15 | print('g') 16 | print('a') 17 | print('b') 18 | print('c') 19 | print('d') 20 | print('e') 21 | print('f') 22 | print('g') 23 | print('a') 24 | print('b') 25 | print('c') 26 | print('d') 27 | print('e') 28 | print('f') 29 | print('g') 30 | print('a') 31 | print('b') 32 | print('c') 33 | print('d') 34 | print('e') 35 | print('f') 36 | print('g') 37 | print('a') 38 | print('b') 39 | print('c') 40 | print('d') 41 | print('e') 42 | print('f') 43 | print('g') 44 | print('a') 45 | print('b') 46 | print('c') 47 | print('d') 48 | print('e') 49 | print('f') 50 | print('g') 51 | print('a') 52 | print('b') 53 | print('c') 54 | print('d') 55 | print('e') 56 | print('f') 57 | print('g') 58 | print('a') 59 | print('b') 60 | print('c') 61 | print('d') 62 | print('e') 63 | print('f') 64 | print('g') 65 | print('a') 66 | print('b') 67 | print('c') 68 | print('d') 69 | print('e') 70 | print('f') 71 | print('g') 72 | print('a') 73 | print('b') 74 | print('c') 75 | print('d') 76 | print('e') 77 | print('f') 78 | print('g') 79 | print('c') 80 | print('d') 81 | print('e') 82 | print('f') 83 | print('g') 84 | print('a') 85 | print('b') 86 | print('c') 87 | print('d') 88 | print('e') 89 | print('f') 90 | print('g') 91 | print('a') 92 | print('b') 93 | print('c') 94 | print('d') 95 | print('e') 96 | print('f') 97 | print('g') 98 | print('c') 99 | print('d') 100 | print('e') 101 | print('f') 102 | print('g') 103 | print('a') 104 | print('b') 105 | print('c') 106 | print('d') 107 | print('e') 108 | print('f') 109 | print('g') 110 | print('a') 111 | print('b') 112 | print('c') 113 | print('d') 114 | print('e') 115 | print('f') 116 | print('g') 117 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case25_django.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.views import View 3 | 4 | 5 | class ReviewView(View): 6 | reviews = ['review'] # List of reviews as plain strings 7 | 8 | def get(self, request, *args, **kwargs): 9 | return render(request, 'book/reviews.html', context={'reviews': self.reviews}) 10 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case26_from_stepik.py: -------------------------------------------------------------------------------- 1 | a, b = input().split() 2 | print(int(a) + int(b)) 3 | 4 | 5 | def fooBar(): 6 | var = 1 7 | print( 8 | "Hello" 9 | "World" 10 | ) 11 | 12 | 13 | x = 42 # noqa: E222,E305 14 | text = "This line is longer than 99 characters. This line is longer than 99 characters. This line is longer than 99 characters" 15 | pass 16 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case27_using_requests.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | 4 | def do_search(bookstore_url, params): 5 | return requests.get(url=bookstore_url, 6 | params=params) 7 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case29_whitespaces.py: -------------------------------------------------------------------------------- 1 | print('qqq') 2 | 3 | print('www') 4 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case2_boolean_expressions.py: -------------------------------------------------------------------------------- 1 | 2 | a = int(input()) 3 | b = int(input()) 4 | c = int(input()) 5 | d = int(input()) 6 | 7 | if a > b: 8 | print('a > b') 9 | 10 | if a > b and a > b: 11 | print('a > b again') 12 | 13 | if a > b and a < d: 14 | print('b < a < d') 15 | 16 | if not a > b: 17 | print('not a > b') 18 | 19 | if b < a < d: 20 | print('b < a < d again') 21 | 22 | if a > b == True: 23 | print('a > b and True') 24 | 25 | if True: 26 | print('qqq') 27 | 28 | enabled = False # It does not work now 29 | if a > b and b < c and c > d or c < a and enabled: 30 | print('Too complex expression') 31 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case30_allow_else_return.py: -------------------------------------------------------------------------------- 1 | def calculate(action: str, operand1: int, operand2: int) -> int: 2 | if action == '+': 3 | return operand1 + operand2 4 | elif action == '-': 5 | return operand1 - operand2 6 | elif action == '*': 7 | return operand1 * operand2 8 | else: 9 | raise ValueError(f'Unknown action {action}') 10 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case31_spellcheck.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | number = math.sqrt(float(input())) 4 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case33_commas.py: -------------------------------------------------------------------------------- 1 | # Wrong C-812 2 | from math import ( 3 | log 4 | ) 5 | 6 | # Correct 7 | from math import ( 8 | sin, 9 | ) 10 | 11 | # Wrong C-812 12 | bad_multiline_dict = { 13 | "first": 1, 14 | "second": 2 15 | } 16 | 17 | # Correct 18 | good_multiline_dict = { 19 | "first": 1, 20 | "second": 2, 21 | } 22 | 23 | # Wrong C-812 24 | bad_multiline_list = [ 25 | 1, 26 | 2, 27 | 3 28 | ] 29 | 30 | # Correct 31 | good_multiline_list = [ 32 | 1, 33 | 2, 34 | 3, 35 | ] 36 | 37 | # Wrong C-812 38 | bad_multiline_tuple = ( 39 | 3, 40 | 4 41 | ) 42 | 43 | good_multiline_tuple = ( 44 | 3, 45 | 4, 46 | ) 47 | 48 | 49 | # Wrong C-812 50 | def bad_function( 51 | a, 52 | b 53 | ): 54 | return log(a, b) 55 | 56 | 57 | bad_function( 58 | 1, 59 | 2 60 | ) 61 | 62 | bad_function( 63 | a=1, 64 | b=2 65 | ) 66 | 67 | 68 | # Correct 69 | def good_function( 70 | a, 71 | b, 72 | ): 73 | return a + sin(b) 74 | 75 | 76 | good_function( 77 | 1, 78 | 2, 79 | ) 80 | 81 | good_function( 82 | a=1, 83 | b=2, 84 | ) 85 | 86 | # Wrong: C-813 87 | print( 88 | "Hello", 89 | "World" 90 | ) 91 | 92 | # Correct 93 | print( 94 | "Hello", 95 | "World", 96 | ) 97 | 98 | 99 | # Wrong: C-816 100 | def bad_function_with_unpacking( 101 | a, 102 | b, 103 | **kwargs 104 | ): 105 | pass 106 | 107 | 108 | # Correct 109 | def good_function_with_unpacking( 110 | a, 111 | b, 112 | **kwargs, 113 | ): 114 | pass 115 | 116 | 117 | # Wrong: C-815 118 | good_function_with_unpacking( 119 | 1, 120 | 2, 121 | **good_multiline_dict 122 | ) 123 | 124 | # Correct 125 | good_function_with_unpacking( 126 | 1, 127 | 2, 128 | **good_multiline_dict, 129 | ) 130 | 131 | # Wrong: C-818 132 | bad_comma = 1, 133 | 134 | # Correct 135 | good_comma = (1,) 136 | 137 | # Wrong: C-819 138 | bad_list = [1, 2, 3, ] 139 | 140 | # Correct: 141 | good_list = [1, 2, 3] 142 | 143 | # Wrong: C-819 144 | bad_dict = {"1": 1, "2": 2, "3": 3, } 145 | 146 | # Correct: 147 | good_dict = {"1": 1, "2": 2, "3": 3} 148 | 149 | # Wrong: C-819 150 | bad_tuple = (1, 2, 3,) 151 | 152 | # Correct 153 | good_tuple = (1, 2, 3) 154 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case34_cohesion.py: -------------------------------------------------------------------------------- 1 | from math import sqrt 2 | 3 | 4 | class BadClass: 5 | def __init__(self, x: int, y: int): 6 | self.x = x 7 | self.y = y 8 | 9 | @staticmethod 10 | def length(x: int, y: int) -> float: 11 | return sqrt(x ** 2 + y ** 2) 12 | 13 | @staticmethod 14 | def dot(self_x: int, self_y: int, other_x: int, other_y: int) -> int: 15 | return self_x * other_x + self_y * other_y 16 | 17 | 18 | class GoodClass(object): 19 | def __init__(self, x: int, y: int): 20 | self.x = x 21 | self.y = y 22 | 23 | @property 24 | def length(self) -> float: 25 | return sqrt(self.dot(self.x, self.y)) 26 | 27 | def dot(self, other_x: int, other_y: int) -> int: 28 | return self.x * other_x + self.y * other_y 29 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case36_unpacking.py: -------------------------------------------------------------------------------- 1 | [a, b, c], [x, y, z] = (sorted(map(int, input().split())) for _ in 'lm') 2 | if [a, b, c] == [x, y, z]: 3 | a = "Boxes are equal" 4 | elif a <= x and b <= y and c <= z: 5 | a = "The first box is smaller than the second one" 6 | elif a >= x and b >= y and c >= z: 7 | a = "The first box is larger than the second one" 8 | else: 9 | a = "Boxes are incomparable" 10 | print(a) 11 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case37_wildcard_import.py: -------------------------------------------------------------------------------- 1 | from math import * 2 | 3 | 4 | def quick_reversed_sqrt(number): 5 | """ 6 | It's quick. Trust me. 7 | """ 8 | return 1 / sqrt(number) 9 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case38_spellcheck.py: -------------------------------------------------------------------------------- 1 | from lxml import etree 2 | 3 | root = etree.fromstring(input()) 4 | children = root.getchildren(root) 5 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case39_no_issues.py: -------------------------------------------------------------------------------- 1 | print("Hello, world!") 2 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case3_redefining_builtin.py: -------------------------------------------------------------------------------- 1 | a = int(input()) 2 | b = int(input()) 3 | 4 | range = range(a, b + 1) 5 | 6 | list = list(filter(lambda x: x % 3 == 0, range)) 7 | print(sum(list) / len(list)) 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case4_naming.py: -------------------------------------------------------------------------------- 1 | def GREETING(): 2 | print('hi!') 3 | 4 | 5 | class myclass: 6 | 7 | def __init__(self, a, b, C): 8 | self.A = a 9 | self.B = b 10 | self.C = C 11 | 12 | def myFun(self): 13 | print(f'hello 1 {self.A}') 14 | 15 | def my_fun(self, QQ): 16 | print('hello 2 {}'.format(QQ)) 17 | 18 | @classmethod 19 | def test_fun(first): 20 | print('hello 3') 21 | 22 | 23 | valid_variable = 'ok' 24 | invalidVariable = 'invalid' 25 | 26 | print(valid_variable) 27 | print(invalidVariable) 28 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case5_returns.py: -------------------------------------------------------------------------------- 1 | def f(x): 2 | if x <= -2: 3 | return 1 - (x + 2) ** 2 4 | elif -2 < x <= 2: 5 | return -(x / 2) 6 | elif x > 2: 7 | return 1 + (x - 2) ** 2 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case6_unused_variables.py: -------------------------------------------------------------------------------- 1 | 2 | def fun(param): 3 | a = 10 4 | b = 20 5 | c = 30 6 | print(c) 7 | d = 40 8 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case7_empty_lines.py: -------------------------------------------------------------------------------- 1 | def fun(): 2 | pass 3 | 4 | class Person: 5 | 6 | def __init__(self, name, age, gender): 7 | self.name = name 8 | self.age = age 9 | 10 | 11 | self.gender = gender 12 | def add_age(self, value): 13 | self.age += value 14 | 15 | 16 | def minus_age(self, value): 17 | self.age -= value 18 | 19 | class AnotherClass: 20 | def do_something(self): 21 | print(1) 22 | 23 | print(10) 24 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case8_good_class.py: -------------------------------------------------------------------------------- 1 | class Student: 2 | 3 | def __init__(self, name, last_name, birth_year): 4 | self.name = name 5 | self.last_name = last_name 6 | self.birth_year = birth_year 7 | 8 | 9 | student_name = Student(input(), input(), input()) 10 | print(student_name.name[0]) 11 | -------------------------------------------------------------------------------- /test/resources/inspectors/python/case_duplicates.py: -------------------------------------------------------------------------------- 1 | a, b = input().split() 2 | print(int(a) + int(b)) 3 | 4 | 5 | def fooBar(): 6 | var = 1 7 | print( 8 | "Hello" 9 | "World" 10 | ) 11 | 12 | 13 | x = 42 # noqa: E222,E305 14 | text = "This line is longer than 99 characters. This line is longer than 99 characters. This line is longer than 99 characters" 15 | pass 16 | -------------------------------------------------------------------------------- /test/resources/inspectors/python_ast/function.py: -------------------------------------------------------------------------------- 1 | def foo(): 2 | print(42) 3 | print(42) 4 | print(42) 5 | print(42) 6 | print(42) 7 | print(42) 8 | print(42) 9 | print(42) 10 | print(42) 11 | print(42) 12 | print(42) 13 | print(42) 14 | print(42) 15 | print(42) 16 | print(42) 17 | -------------------------------------------------------------------------------- /test/resources/inspectors/python_ast/many_bool_expressions.py: -------------------------------------------------------------------------------- 1 | a = True 2 | b = False 3 | c = True 4 | 5 | if a or b: 6 | print('Hello') 7 | 8 | if b or c: 9 | print('world') 10 | 11 | if not c and a: 12 | print('!') -------------------------------------------------------------------------------- /test/resources/inspectors/python_ast/one_bool_expression.py: -------------------------------------------------------------------------------- 1 | a, b, c, d, e, f = True, True, True, True, True, True 2 | if a or b and c or not d and e or f: 3 | print('Hello') 4 | -------------------------------------------------------------------------------- /test/resources/inspectors/spring/case1/test_promiscuous_controller.java: -------------------------------------------------------------------------------- 1 | package org.hyperskill.webquizengine.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | 7 | @Controller 8 | @X 9 | class ManyRoutesController { 10 | 11 | 12 | @RequestMapping 13 | public void m1() { 14 | 15 | 16 | } 17 | 18 | @RequestMapping 19 | public void m2() { 20 | 21 | 22 | } 23 | 24 | @RequestMapping 25 | public void m3() { 26 | 27 | 28 | } 29 | 30 | @RequestMapping 31 | public void m4() { 32 | 33 | 34 | } 35 | 36 | @RequestMapping 37 | public void m5() { 38 | 39 | 40 | } 41 | 42 | @RequestMapping 43 | public void m6() { 44 | 45 | } 46 | @RequestMapping 47 | public void m7() { 48 | 49 | } 50 | @RequestMapping 51 | public void m8() { 52 | 53 | } 54 | 55 | @RequestMapping 56 | public void m9() { 57 | 58 | } 59 | @RequestMapping 60 | public void m10() { 61 | 62 | } 63 | 64 | @RequestMapping 65 | public void m11() { 66 | 67 | } 68 | @RequestMapping 69 | public void m12() { 70 | 71 | } 72 | } -------------------------------------------------------------------------------- /test/resources/inspectors/spring/case2/test_class_with_booleans.java: -------------------------------------------------------------------------------- 1 | class ClassWithBooleans { 2 | private boolean enabled = true; 3 | private boolean isTyped = true; 4 | private boolean count = false; 5 | private boolean correct = true; 6 | private int isValid = 1; 7 | 8 | public boolean getEnabled() { 9 | return enabled; 10 | } 11 | 12 | public boolean isTyped() { 13 | return isTyped; 14 | } 15 | 16 | public boolean getCount() { 17 | return count; 18 | } 19 | 20 | public boolean isEnabled() { 21 | return enabled; 22 | } 23 | 24 | public boolean isCount() { 25 | return count; 26 | } 27 | 28 | public boolean isCorrect() { 29 | return correct; 30 | } 31 | 32 | public int getIsValid() { 33 | return isValid; 34 | } 35 | 36 | 37 | public static void main(String[] args) { 38 | ClassWithBooleans object = new ClassWithBooleans(); 39 | System.out.println(object.isTyped()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = -rsxX -l --tb=short --strict 3 | xfail_strict = true 4 | norecursedirs = .* venv src *.egg dist build --------------------------------------------------------------------------------