Skip to content

Commit

Permalink
feat(linter): added --statistics flag to print summary of linter find…
Browse files Browse the repository at this point in the history
…ings

closes #389
  • Loading branch information
christopherpickering committed Sep 19, 2022
1 parent 756c760 commit 489decb
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 16 deletions.
10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Expand Up @@ -5,13 +5,13 @@ exclude: >
)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
rev: v4.3.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- repo: https://github.com/myint/autoflake
rev: v1.4
rev: v1.6.0
hooks:
- id: autoflake
exclude: &fixtures tests/functional/|tests/input|tests/extensions/data|tests/regrtest_data/|tests/data/
Expand All @@ -22,7 +22,7 @@ repos:
- --remove-duplicate-keys
- --remove-unused-variables
- repo: https://github.com/asottile/pyupgrade
rev: v2.31.0
rev: v2.38.0
hooks:
- id: pyupgrade
args: [--py36-plus]
Expand All @@ -33,11 +33,11 @@ repos:
exclude: docs*
additional_dependencies: [toml]
- repo: https://github.com/psf/black
rev: 22.1.0
rev: 22.8.0
hooks:
- id: black
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.2.0
rev: v2.4.0
hooks:
- id: pretty-format-ini
args: [--autofix]
Expand Down
4 changes: 3 additions & 1 deletion docs/src/docs/getting-started.md
Expand Up @@ -49,7 +49,9 @@ Options:
--preserve-blank-lines Attempt to preserve blank lines.
--format-css Also format contents of <style> tags.
--format-js Also format contents of <script> tags.
--configuration Path to global configuration file in .djlintrc format
--configuration PATH Path to global configuration file in .djlintrc format
--statistics Count the number of occurrences of each
error/warning code.
-h, --help Show this message and exit.
```

Expand Down
4 changes: 3 additions & 1 deletion docs/src/fr/docs/getting-started.md
Expand Up @@ -49,7 +49,9 @@ Options:
--preserve-blank-lines Attempt to preserve blank lines.
--format-css Also format contents of <style> tags.
--format-js Also format contents of <script> tags.
--configuration Path to global configuration file in .djlintrc format
--configuration PATH Path to global configuration file in .djlintrc format
--statistics Count the number of occurrences of each
error/warning code.
-h, --help Show this message and exit.
```

Expand Down
4 changes: 3 additions & 1 deletion docs/src/ru/docs/getting-started.md
Expand Up @@ -49,7 +49,9 @@ Options:
--preserve-blank-lines Attempt to preserve blank lines.
--format-css Also format contents of <style> tags.
--format-js Also format contents of <script> tags.
--configuration Path to global configuration file in .djlintrc format
--configuration PATH Path to global configuration file in .djlintrc format
--statistics Count the number of occurrences of each
error/warning code.
-h, --help Show this message and exit.
```

Expand Down
7 changes: 7 additions & 0 deletions src/djlint/__init__.py
Expand Up @@ -122,6 +122,11 @@
required=False,
help="Path to global configuration file in .djlintrc format",
)
@click.option(
"--statistics",
is_flag=True,
help="Count the number of occurrences of each error/warning code.",
)
@colorama_text(autoreset=True)
def main(
src: List[str],
Expand All @@ -141,6 +146,7 @@ def main(
format_css: bool,
format_js: bool,
configuration: Optional[str],
statistics: bool,
) -> None:
"""djLint · HTML template linter and formatter."""
config = Config(
Expand All @@ -161,6 +167,7 @@ def main(
format_css=format_css,
format_js=format_js,
configuration=configuration,
statistics=statistics,
)

temp_file = None
Expand Down
59 changes: 51 additions & 8 deletions src/djlint/output.py
@@ -1,7 +1,8 @@
"""Build djLint console output."""
import shutil
from collections import Counter
from pathlib import Path
from typing import Any, Dict, List
from typing import Any, Dict, List, Optional

import regex as re
from click import echo
Expand Down Expand Up @@ -33,14 +34,22 @@ def print_output(
if config.stdin is False or config.lint:
echo()

for error in sorted(file_errors, key=lambda x: next(iter(list(x.values())[0]))):
if error.get("format_message") and config.stdin is False:
# reformat message
format_error_count += build_check_output(error["format_message"], config)
if config.statistics:
lint_error_count = build_stats_output(
[x.get("lint_message") for x in file_errors], config
)

else:
for error in sorted(file_errors, key=lambda x: next(iter(list(x.values())[0]))):
if error.get("format_message") and config.stdin is False:
# reformat message
format_error_count += build_check_output(
error["format_message"], config
)

if error.get("lint_message"):
# lint message
lint_error_count += build_output(error["lint_message"], config)
if error.get("lint_message"):
# lint message
lint_error_count += build_output(error["lint_message"], config)

tense_message = (
build_quantity(format_error_count) + " would be"
Expand Down Expand Up @@ -180,3 +189,37 @@ def build_quantity_tense(size: int) -> str:
+ " "
+ ("were" if size > 1 or size == 0 else "was")
)


def build_stats_output(errors: List[Optional[Any]], config: Config) -> int:
"""Build output for linter statistics."""
if len(errors) == 0:
return 0

codes = []
for error in errors:
if error:
for code in list(error.values())[0]:
codes.append(code["code"])

messages = {
rule["rule"]["name"]: rule["rule"]["message"] for rule in config.linter_rules
}

if messages and codes:

longest_code = len(max(messages.keys(), key=len))
longest_count = len(
str(max(Counter(codes).values(), key=lambda x: len(str(x))))
)

for code in sorted(Counter(codes).items()):

code_space = (longest_code - len(str(code[0]))) * " "
count_space = (longest_count - len(str(code[1]))) * " "

echo(
f"{Fore.YELLOW}{code[0]}{Fore.BLUE} {code_space}{code[1]}{Style.RESET_ALL} {count_space}{messages[code[0]]}"
)

return sum(Counter(codes).values())
3 changes: 3 additions & 0 deletions src/djlint/settings.py
Expand Up @@ -206,6 +206,7 @@ def __init__(
format_css: bool = False,
format_js: bool = False,
configuration: Optional[str] = None,
statistics: bool = False,
):

self.reformat = reformat
Expand Down Expand Up @@ -306,6 +307,8 @@ def __init__(
)
)

self.statistics = statistics

# base options
default_indent = 4
if not indent:
Expand Down
14 changes: 14 additions & 0 deletions tests/test_linter/test_linter.py
Expand Up @@ -954,3 +954,17 @@ def test_ignoring_rules(runner: CliRunner, tmp_file: TextIO) -> None:
)
result = runner.invoke(djlint, [tmp_file.name])
assert "H006" not in result.output


def test_statistics_empty(runner: CliRunner, tmp_file: TextIO) -> None:
write_to_file(tmp_file.name, b"")
result = runner.invoke(djlint, [tmp_file.name, "--statistics"])

assert result.exit_code == 0


def test_statistics_with_results(runner: CliRunner, tmp_file: TextIO) -> None:
write_to_file(tmp_file.name, b"<div>")
result = runner.invoke(djlint, [tmp_file.name, "--statistics"])

assert result.exit_code == 1

0 comments on commit 489decb

Please sign in to comment.