Use same yaml structure as cling-tidy

This commit is contained in:
jspijker 2022-11-21 10:51:08 +01:00
parent 2b90807326
commit 4b455d45e9
8 changed files with 85 additions and 124 deletions

View file

@ -10,7 +10,7 @@ dependencies = [
]
[project.scripts]
printer-linter = "printerlinter.terminal:main"
printer-linter = "terminal:main"
[build-system]
requires = ["setuptools"]

View file

@ -1,20 +1,7 @@
from .defintion import Definition
from .diagnostic import Diagnostic
from .factory import create
from .meshes import Meshes
from .profile import Profile
__all__ = ["Profile", "Definition", "Meshes", "Diagnostic", "create"]
def create(file, settings):
if not file.exists():
return None
if ".inst" in file.suffixes and ".cfg" in file.suffixes:
return Profile(file, settings)
if ".def" in file.suffixes and ".json" in file.suffixes:
if file.stem in ("fdmprinter.def", "fdmextruder.def"):
return None
return Definition(file, settings)
if file.parent.stem == "meshes":
return Meshes(file, settings)
return None

View file

@ -1,7 +1,9 @@
import json
import re
from pathlib import Path
from .diagnostic import Diagnostic
from .replacement import Replacement
class Definition:
@ -11,6 +13,8 @@ class Definition:
self._defs = {}
self._getDefs(file)
self._content = self._file.read_text()
settings = {}
for k, v in self._defs["fdmprinter"]["settings"].items():
self._getSetting(k, v, settings)
@ -32,24 +36,25 @@ class Definition:
definition_name = list(self._defs.keys())[0]
definition = self._defs[definition_name]
if "overrides" in definition and definition_name != "fdmprinter":
keys = list(definition["overrides"].keys())
for key, value_dict in definition["overrides"].items():
is_redefined, value, parent = self._isDefinedInParent(key, value_dict, definition['inherits'])
if is_redefined:
termination_key = keys.index(key) + 1
if termination_key >= len(keys):
# FIXME: find the correct end sequence for now assume it is on the same line
termination_seq = None
else:
termination_seq = keys[termination_key]
yield Diagnostic("diagnostic-definition-redundant-override",
f"Overriding **{key}** with the same value (**{value}**) as defined in parent definition: **{definition['inherits']}**",
self._file,
key,
termination_seq)
redefined = re.compile(r'.*(\"' + key + r'\"[\s\S]*?\{)[\s\S]*?(\}[,\"]?)')
found = redefined.search(self._content)
yield Diagnostic(
file = self._file,
diagnostic_name = "diagnostic-definition-redundant-override",
message = f"Overriding **{key}** with the same value (**{value}**) as defined in parent definition: **{definition['inherits']}**",
level = "Warning",
offset = found.span(0)[0],
replacements = [Replacement(
file = self._file,
offset = found.span(1)[0],
length = found.span(2)[1] - found.span(1)[0],
replacement_text = "")]
)
def checkValueOutOfBounds(self):
pass
def _getSetting(self, name, setting, settings):

View file

@ -1,85 +1,20 @@
class Diagnostic:
def __init__(self, illness, msg, file, key=None, termination_seq=None):
self.illness = illness
self.key = key
self.msg = msg
def __init__(self, file, diagnostic_name, message, level, offset, replacements=None):
self.file = file
self._lines = None
self._location = None
self._fix = None
self._content_block = None
self._termination_seq = termination_seq
@property
def location(self):
if self._location:
return self._location
if not self._lines:
with open(self.file, "r") as f:
if not self.is_text_file:
self._fix = ""
return self._fix
self._lines = f.readlines()
start_location = {"col": 1, "line": 1}
end_location = {"col": len(self._lines[-1]) + 1, "line": len(self._lines) + 1}
if self.key is not None:
for lino, line in enumerate(self._lines, 1):
if f'"{self.key}":' in line:
col = line.index(f'"{self.key}":') + 1
start_location = {"col": col, "line": lino}
if self._termination_seq is None:
end_location = {"col": len(line) + 1, "line": lino}
break
if f'"{self._termination_seq}":' in line:
col = line.index(f'"{self._termination_seq}":') + 1
end_location = {"col": col, "line": lino}
self._location = {"start": start_location, "end": end_location}
return self._location
@property
def is_text_file(self):
return self.file.name.split(".", maxsplit=1)[-1] in ("def.json", "inst.cfg")
@property
def content_block(self):
if self._content_block:
return self._content_block
if not self._lines:
if not self.is_text_file:
self._fix = ""
return self._fix
with open(self.file, "r") as f:
self._lines = f.readlines()
start_line = self.location["start"]["line"] - 1
end_line = self.location["end"]["line"] - 1
self._content_block = "\n".join(self._lines[start_line:end_line])
return self._content_block
@property
def fix(self):
if self._fix:
return self._fix
if not self._lines:
if not self.is_text_file:
self._fix = ""
return self._fix
with open(self.file, "r") as f:
self._lines = f.readlines()
start_line = self.location["start"]["line"] - 2
start_col = 0
end_line = self.location["end"]["line"] - 1
end_col = len(self._lines[start_line:end_line - 1]) + self.location["start"]["col"] - 4 # TODO: double check if 4 holds in all instances
self._fix = self.content_block[start_col:end_col]
return self._fix
self.diagnostic_name = diagnostic_name
self.message = message
self.offset = offset
self.level = level
self.replacements = replacements
def toDict(self):
diagnostic_dict = {"diagnostic": self.illness, "message": self.msg}
if self.is_text_file:
diagnostic_dict |= {"fix": self.fix, "lino": self.location, "content": self.content_block}
diagnostic_dict = {"DiagnosticName": self.diagnostic_name,
"DiagnosticMessage": {
"Message": self.message,
"FilePath": self.file.as_posix(),
"FileOffset": self.offset,
"Replacements": [] if self.replacements is None else [r.toDict() for r in self.replacements],
},
"Level": self.level
}
return diagnostic_dict

View file

@ -0,0 +1,17 @@
from .profile import Profile
from .defintion import Definition
from .meshes import Meshes
def create(file, settings):
if not file.exists():
return None
if ".inst" in file.suffixes and ".cfg" in file.suffixes:
return Profile(file, settings)
if ".def" in file.suffixes and ".json" in file.suffixes:
if file.stem in ("fdmprinter.def", "fdmextruder.def"):
return None
return Definition(file, settings)
if file.parent.stem == "meshes":
return Meshes(file, settings)
return None

View file

@ -20,15 +20,22 @@ class Meshes:
def checkFileFormat(self):
if self._file.suffix.lower() not in (".3mf", ".obj", ".stl"):
yield Diagnostic("diagnostic-mesh-file-extension",
f"Extension **{self._file.suffix}** not supported, use **3mf**, **obj** or **stl**",
self._file)
yield Diagnostic(
file = self._file,
diagnostic_name = "diagnostic-mesh-file-extension",
message = f"Extension **{self._file.suffix}** not supported, use **3mf**, **obj** or **stl**",
level = "Error"
)
yield
def checkFileSize(self):
if self._file.stat().st_size > self._max_file_size:
yield Diagnostic("diagnostic-mesh-file-size",
f"Mesh file with a size **{self._file.stat().st_size}** is bigger then allowed maximum of **{self._max_file_size}**",
self._file)
yield Diagnostic(
file = self._file,
diagnostic_name = "diagnostic-mesh-file-size",
message = f"Mesh file with a size **{self._file.stat().st_size}** is bigger then allowed maximum of **{self._max_file_size}**",
level = "Error",
offset = 0
)
yield

View file

@ -0,0 +1,12 @@
class Replacement:
def __init__(self, file, offset, length, replacement_text):
self.file = file
self.offset = offset
self.length = length
self.replacement_text = replacement_text
def toDict(self):
return {"FilePath": self.file.as_posix(),
"Offset": self.offset,
"Length": self.length,
"ReplacementText": self.replacement_text}

View file

@ -8,22 +8,20 @@ from pathlib import Path
import yaml
from . import create
from printerlinter import factory
def examineFile(file, settings):
patient = create(file, settings)
patient = factory.create(file, settings)
if patient is None:
return {}
full_body_check = {f"{file.as_posix()}": []}
body_check = []
for diagnostic in patient.check():
if diagnostic:
full_body_check[f"{file.as_posix()}"].append(diagnostic.toDict())
body_check.append(diagnostic.toDict())
if len(full_body_check[f"{file.as_posix()}"]) == 0:
del full_body_check[f"{file.as_posix()}"]
return full_body_check
return body_check
def fixFile(file, settings, full_body_check):
@ -101,13 +99,13 @@ def main():
settings = yaml.load(f, yaml.FullLoader)
if to_fix or to_diagnose:
full_body_check = {}
full_body_check = {"Diagnostics": []}
for file in files:
if file.is_dir():
for fp in file.rglob("**/*"):
full_body_check |= examineFile(fp, settings)
full_body_check["Diagnostics"].append(examineFile(fp, settings))
else:
full_body_check |= examineFile(file, settings)
full_body_check["Diagnostics"].append(examineFile(file, settings))
results = yaml.dump(full_body_check, default_flow_style=False, indent=4, width=240)
if report: