Add Go and Rust parsers
This commit is contained in:
89
depaudit/parsers/go.py
Normal file
89
depaudit/parsers/go.py
Normal file
@@ -0,0 +1,89 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from depaudit.parsers import Parser, ParsedManifest, Dependency
|
||||
|
||||
|
||||
class GoParser(Parser):
|
||||
language = "go"
|
||||
|
||||
def can_parse(self, file_path: Path) -> bool:
|
||||
return file_path.name == "go.mod"
|
||||
|
||||
def parse(self, file_path: Path) -> ParsedManifest:
|
||||
content = file_path.read_text(encoding="utf-8")
|
||||
lines = content.split("\n")
|
||||
|
||||
manifest = ParsedManifest(
|
||||
language=self.language,
|
||||
file_path=file_path,
|
||||
)
|
||||
|
||||
i = 0
|
||||
in_require_block = False
|
||||
current_line_indent = 0
|
||||
|
||||
while i < len(lines):
|
||||
line = lines[i].strip()
|
||||
original_line = lines[i]
|
||||
|
||||
if not line or line.startswith("//"):
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if line.startswith("module"):
|
||||
manifest.project_name = line.split()[1].strip()
|
||||
elif line.startswith("go"):
|
||||
pass
|
||||
elif line.startswith("require"):
|
||||
in_require_block = True
|
||||
current_line_indent = len(lines[i]) - len(lines[i].lstrip())
|
||||
self._parse_require(line, file_path, manifest)
|
||||
elif in_require_block:
|
||||
current_indent = len(lines[i]) - len(lines[i].lstrip())
|
||||
if current_indent > current_line_indent and not line.startswith("//"):
|
||||
self._parse_require(lines[i], file_path, manifest)
|
||||
else:
|
||||
in_require_block = False
|
||||
|
||||
i += 1
|
||||
|
||||
return manifest
|
||||
|
||||
def _parse_require(
|
||||
self, line: str, file_path: Path, manifest: ParsedManifest
|
||||
) -> None:
|
||||
content = line.strip()
|
||||
if content.startswith("//"):
|
||||
return
|
||||
|
||||
if content.startswith("require"):
|
||||
content = content[len("require"):].strip()
|
||||
if content.startswith("("):
|
||||
content = content[1:]
|
||||
if content.endswith(")"):
|
||||
content = content[:-1]
|
||||
|
||||
if not content:
|
||||
return
|
||||
|
||||
parts = content.split()
|
||||
i = 0
|
||||
while i < len(parts):
|
||||
if parts[i].startswith("//"):
|
||||
break
|
||||
name = parts[i]
|
||||
version = ""
|
||||
if i + 1 < len(parts) and not parts[i + 1].startswith("/"):
|
||||
version = parts[i + 1]
|
||||
i += 2
|
||||
else:
|
||||
i += 1
|
||||
|
||||
if name:
|
||||
indirect = "// indirect" in line or "(// indirect)" in line or "(indirect)" in line
|
||||
manifest.dependencies.append(
|
||||
self._create_dependency(file_path, name, version, indirect=indirect)
|
||||
)
|
||||
Reference in New Issue
Block a user