Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions scripts/codelens.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,19 @@ def _suggest_fix(command: str, error: Exception) -> str:

LAST_WORKSPACE_FILE = ".codelens_last_workspace"

# Canonical set of ``--format`` choices, in dispatch order. The first six are
# the JSON-family / graph formats (issue #17, #59). The final five are the
# Phase 2 developer-tool formats (issue #52): ``text``, ``junit-xml``,
# ``emacs``, ``vim``, ``gitlab-sast`` — all implemented in
# ``formatters.format_output`` and each verified to produce output. This single
# tuple is the source of truth for every argparse ``choices=`` list and the
# manual pre-parse guard below, so the CLI can never expose fewer formats than
# it actually supports.
_FORMAT_CHOICES = (
"json", "markdown", "ai", "sarif", "compact", "graphml",
"text", "junit-xml", "emacs", "vim", "gitlab-sast",
)


def _save_last_workspace(workspace: str) -> None:
"""Save the last used workspace path to a global cache file."""
Expand Down Expand Up @@ -1161,8 +1174,8 @@ def main():
format_args = ["--format"]
if "-f" not in existing_option_strings:
format_args.append("-f")
sub.add_argument(*format_args, choices=["json", "markdown", "ai", "sarif", "compact", "graphml"], default=None,
help="Output format: json, markdown, ai (normalized schema), sarif (GitHub/VS Code), compact (token-efficient single-char keys), or graphml (GraphML 1.0 XML for graph-producing commands)")
sub.add_argument(*format_args, choices=list(_FORMAT_CHOICES), default=None,
help="Output format: json, markdown, ai (normalized schema), sarif (GitHub/VS Code), compact (token-efficient single-char keys), graphml (GraphML 1.0 XML for graph-producing commands), text, junit-xml, emacs, vim, or gitlab-sast")

# Add AI-optimized flags to subparser ONLY if the command doesn't already have them
if "top" not in existing_dests:
Expand Down Expand Up @@ -1195,8 +1208,8 @@ def main():
# Global format option (works before subcommand)
# Default: "ai" if CODELENS_AI_MODE is set (for AI consumers), else "json"
_default_format = "ai" if os.environ.get("CODELENS_AI_MODE", "").lower() in ("1", "true", "yes") else "json"
parser.add_argument("--format", "-f", choices=["json", "markdown", "ai", "sarif", "compact", "graphml"], default=_default_format,
help=f"Output format (default: {_default_format}. Set CODELENS_AI_MODE=1 for ai default. compact = token-efficient single-char keys. graphml = GraphML XML for graph-producing commands)")
parser.add_argument("--format", "-f", choices=list(_FORMAT_CHOICES), default=_default_format,
help=f"Output format (default: {_default_format}. Set CODELENS_AI_MODE=1 for ai default. compact = token-efficient single-char keys. graphml = GraphML XML for graph-producing commands. Also: text, junit-xml, emacs, vim, gitlab-sast)")
parser.add_argument("--db-path", default=None,
help="Custom path for SQLite database (default: .codelens/codelens.db)")
# Issue #157: --diff-base <ref> restricts analysis to files changed
Expand Down Expand Up @@ -1243,11 +1256,11 @@ def main():
arg = sys.argv[i]
if arg in ('-f', '--format') and i + 1 < len(sys.argv):
next_arg = sys.argv[i + 1]
if next_arg in ('json', 'markdown', 'ai', 'sarif', 'compact', 'graphml'):
if next_arg in _FORMAT_CHOICES:
global_format = next_arg
elif arg.startswith('-f=') and arg[3:] in ('json', 'markdown', 'ai', 'sarif', 'compact', 'graphml'):
elif arg.startswith('-f=') and arg[3:] in _FORMAT_CHOICES:
global_format = arg[3:]
elif arg.startswith('--format=') and arg[9:] in ('json', 'markdown', 'ai', 'sarif', 'compact', 'graphml'):
elif arg.startswith('--format=') and arg[9:] in _FORMAT_CHOICES:
global_format = arg[9:]
elif arg == '--top' and i + 1 < len(sys.argv):
try:
Expand Down
6 changes: 5 additions & 1 deletion scripts/formatters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,5 +234,9 @@ def format_output(data: Any, format_type: str = "json", command: str = "",
if format_type == "gitlab-sast":
from formatters.gitlab_sast import format_gitlab_sast
return format_gitlab_sast(data, command, workspace)
# Default: JSON
# Default: JSON. Stamp ``schema_version`` (issue #5) so raw JSON consumers
# get the same output contract as the ``ai`` format. Stamp a shallow copy so
# the caller's dict is never mutated.
if isinstance(data, dict) and "schema_version" not in data:
data = stamp_schema_version(dict(data))
return json.dumps(data, indent=2, ensure_ascii=False)
7 changes: 5 additions & 2 deletions tests/test_formatters_phase2.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,14 +466,17 @@ class TestCLISmoke:
def _run_cli(self, fmt):
env = os.environ.copy()
env["PYTHONPATH"] = SCRIPTS_DIR
# ``security`` is the umbrella command that absorbed the standalone
# ``secrets`` command in the #195 consolidation. Its ``--help`` must
# list the full ``--format`` choice set.
return subprocess.run(
[sys.executable, os.path.join(SCRIPTS_DIR, "codelens.py"),
"secrets", "--format", fmt, "--help"],
"security", "--format", fmt, "--help"],
capture_output=True, text=True, env=env, timeout=30,
)

def test_help_lists_new_formats(self):
"""``codelens secrets --help`` should list the 5 new format choices."""
"""``codelens security --help`` should list the 5 new format choices."""
result = self._run_cli("text")
# The --help output should mention all 5 new formats.
for fmt in ("text", "junit-xml", "emacs", "vim", "gitlab-sast"):
Expand Down
Loading