Skip to content

Commit

Permalink
Add: fix method to spaces_before_dots
Browse files Browse the repository at this point in the history
  • Loading branch information
NiklasHargarter committed Sep 13, 2024
1 parent 207a0a7 commit 02ae116
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 5 deletions.
47 changes: 45 additions & 2 deletions tests/plugins/test_spaces_before_dots.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from pathlib import Path

from tests.plugins import PluginTestCase
from troubadix.helper import CURRENT_ENCODING
from troubadix.plugin import LinterFix
from troubadix.plugins.spaces_before_dots import CheckSpacesBeforeDots


Expand All @@ -30,7 +32,7 @@ def test_fail(self):
script_tag(name:"summary", value:"Foo Bar .");
script_tag(name:"vuldetect", value:"Foo Bar .");
script_tag(name:"insight", value:"Foo Bar .");
script_tag(name:"impact", value:"Foo . Bar");
script_tag(name:"impact", value:"Foo . Bar . Foo");
"""
'script_tag(name:"affected", value:"Foo\n.\nBar.");'
'script_tag(name:"solution", value:"Foo Bar\n.");'
Expand All @@ -40,7 +42,7 @@ def test_fail(self):
)
plugin = CheckSpacesBeforeDots(fake_context)
results = list(plugin.run())
self.assertEqual(len(results), 6)
self.assertEqual(len(results), 7)
self.assertEqual(
results[0].message,
"value of script_tag summary has alteast one occurence of excess"
Expand All @@ -58,3 +60,44 @@ def test_ignore(self):
results = list(plugin.run())

self.assertEqual(len(results), 0)

def test_fix(self):
with self.create_directory() as tempdir:
path = tempdir / "file.nasl"
content = (
"""
script_tag(name:"summary", value:"Foo Bar .");
script_tag(name:"vuldetect", value:"Foo Bar .");
script_tag(name:"insight", value:"Foo Bar .");
script_tag(name:"impact", value:"Foo . Bar . Foo");
"""
'script_tag(name:"affected", value:"Foo\n.\nBar.");'
'script_tag(name:"solution", value:"Foo Bar\n.");'
)
expected_modified_content = (
"""
script_tag(name:"summary", value:"Foo Bar.");
script_tag(name:"vuldetect", value:"Foo Bar.");
script_tag(name:"insight", value:"Foo Bar.");
script_tag(name:"impact", value:"Foo. Bar. Foo");
"""
'script_tag(name:"affected", value:"Foo.\nBar.");'
'script_tag(name:"solution", value:"Foo Bar.");'
)
path.write_text(content, encoding=CURRENT_ENCODING)

fake_context = self.create_file_plugin_context(
nasl_file=path, file_content=content
)

plugin = CheckSpacesBeforeDots(fake_context)

# keep list() to consume the iterator
list(plugin.run())

results = list(plugin.fix())
self.assertEqual(len(results), 1)

self.assertIsInstance(results[0], LinterFix)
modified_content = path.read_text(encoding=CURRENT_ENCODING)
self.assertEqual(modified_content, expected_modified_content)
45 changes: 42 additions & 3 deletions troubadix/plugins/spaces_before_dots.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@
# SPDX-FileCopyrightText: 2024 Greenbone AG
import re
from collections.abc import Iterator
from operator import itemgetter
from pathlib import Path

from troubadix.helper import CURRENT_ENCODING
from troubadix.helper.patterns import (
ScriptTag,
get_script_tag_pattern,
)
from troubadix.plugin import FileContentPlugin, LinterResult, LinterWarning
from troubadix.plugin import (
FileContentPlugin,
LinterFix,
LinterResult,
LinterWarning,
)

TAGS = [
ScriptTag.SUMMARY,
Expand All @@ -22,7 +29,7 @@
# Regex pattern to match:
# 1. A dot preceded and/or followed by any whitespace character (floating between words)
# 2. A dot preceded by any whitespace character at the end of the string
PATTERN = re.compile(r"\s\.(\s|$)")
PATTERN = re.compile(r"\s+\.(\s|$)")


class CheckSpacesBeforeDots(FileContentPlugin):
Expand All @@ -35,14 +42,19 @@ def check_content(
This plugin checks for excess whitespace before a dot
in script_tags that have full sentence values
"""
self.matches = []
if nasl_file.suffix == ".inc":
return
for tag in TAGS:
pattern = get_script_tag_pattern(tag)
match = pattern.search(file_content)
if match:
value = match.group("value")
if PATTERN.search(value):
value_start = match.start("value")

for excess_match in PATTERN.finditer(value):
whitespace_pos = excess_match.start() + value_start
self.matches.append((whitespace_pos, excess_match.group()))
fullmatch = match.group()
yield LinterWarning(
f"value of script_tag {match.group('name')} has alteast"
Expand All @@ -51,3 +63,30 @@ def check_content(
file=nasl_file,
plugin=self.name,
)

def fix(self) -> Iterator[LinterResult]:

if not self.matches:
return

Check warning on line 70 in troubadix/plugins/spaces_before_dots.py

View check run for this annotation

Codecov / codecov/patch

troubadix/plugins/spaces_before_dots.py#L70

Added line #L70 was not covered by tests

# Sort matches by position, descending order to avoid messing up indices during replacement
self.matches.sort(reverse=True, key=itemgetter(0))

file_content = self.context.file_content
for pos, match_str in self.matches:
# Replace the match by removing the excess whitespace before the dot
fixed_str = re.sub(r"\s+\.", ".", match_str)
file_content = (
file_content[:pos]
+ fixed_str
+ file_content[pos + len(match_str) :]
)

with open(self.context.nasl_file, "w", encoding=CURRENT_ENCODING) as f:
f.write(file_content)

yield LinterFix(
"Excess spaces were removed",
file=self.context.nasl_file,
plugin=self.name,
)

0 comments on commit 02ae116

Please sign in to comment.