Files
2026-02-02 21:33:26 +00:00

90 lines
2.7 KiB
Python

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)
)