Skip to content

Commit 6d49fec

Browse files
committed
fix: test line code fix?
1 parent 69d9fb7 commit 6d49fec

File tree

8 files changed

+122
-17
lines changed

8 files changed

+122
-17
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "avrae-ls"
7-
version = "0.7.0"
7+
version = "0.7.1"
88
description = "Language server for Avrae draconic aliases"
99
authors = [
1010
{ name = "1drturtle" }

src/avrae_ls/__main__.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,17 @@ def _print_test_results(results: Iterable[AliasTestResult], workspace_root: Path
202202
passed += 1
203203
continue
204204
if res.error:
205-
if res.error_line is not None:
206-
alias_name = res.case.alias_path.name
207-
print(f" Error (line {res.error_line} {alias_name}): {res.error}")
205+
if res.error_line is not None and res.error_col is not None:
206+
label = f" Execution Error (line {res.error_line} col {res.error_col})"
207+
elif res.error_line is not None:
208+
label = f" Execution Error (line {res.error_line})"
208209
else:
209-
print(f" Error: {res.error}")
210+
label = " Execution Error"
211+
print(_colorize_error_line(label))
212+
print(f" {res.error}")
213+
if res.stdout:
214+
print(f" Stdout: {res.stdout.strip()}")
215+
continue
210216
if res.details:
211217
print(f" {res.details}")
212218
expected_val, actual_val = _summarize_mismatch(res.case.expected, res.actual)
@@ -262,6 +268,12 @@ def _colorize_diff_line(line: str) -> str:
262268
return line
263269

264270

271+
def _colorize_error_line(line: str) -> str:
272+
if not sys.stdout.isatty():
273+
return line
274+
return f"\x1b[31m{line}\x1b[0m"
275+
276+
265277
def _print_labeled_value(label: str, value: str) -> None:
266278
lines = value.splitlines() or [""]
267279
if len(lines) == 1:

src/avrae_ls/alias_preview.py

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class RenderedAlias:
1818
error: Optional[BaseException]
1919
last_value: Any | None = None
2020
error_line: int | None = None
21+
error_col: int | None = None
2122

2223

2324
@dataclass
@@ -81,18 +82,43 @@ def _line_index_for_offset(text: str, offset: int) -> int:
8182
return text.count("\n", 0, offset)
8283

8384

84-
def _error_line_for_match(
85+
def _error_position_for_match(
8586
body: str, match: re.Match[str], error: BaseException, line_offset: int
86-
) -> int | None:
87+
) -> tuple[int | None, int | None]:
8788
base_line = _line_index_for_offset(body, match.start(1))
88-
lineno = getattr(error, "lineno", None)
89-
if isinstance(lineno, int) and lineno > 0 and getattr(error, "text", None) is not None:
90-
line_index = base_line + (lineno - 1)
89+
base_line_start = body.rfind("\n", 0, match.start(1))
90+
base_col = match.start(1) - (base_line_start + 1 if base_line_start != -1 else 0)
91+
line_in_code: int | None = None
92+
col_in_code: int | None = None
93+
node = getattr(error, "node", None)
94+
if node is not None:
95+
node_line = getattr(node, "lineno", None)
96+
if isinstance(node_line, int) and node_line > 0:
97+
line_in_code = node_line
98+
node_col = getattr(node, "col_offset", None)
99+
if isinstance(node_col, int) and node_col >= 0:
100+
col_in_code = node_col
101+
if line_in_code is None:
102+
lineno = getattr(error, "lineno", None)
103+
if isinstance(lineno, int) and lineno > 0:
104+
line_in_code = lineno
105+
offset = getattr(error, "offset", None)
106+
if isinstance(offset, int) and offset > 0:
107+
col_in_code = offset - 1
108+
if line_in_code is not None:
109+
line_index = base_line + (line_in_code - 1)
91110
else:
92111
code = match.group(1)
93112
leading_newlines = len(code) - len(code.lstrip("\n"))
94113
line_index = base_line + leading_newlines
95-
return line_index + line_offset + 1
114+
col_in_code = 0 if col_in_code is None else col_in_code
115+
if col_in_code is None:
116+
col_in_code = 0
117+
if line_in_code is None or line_in_code == 1:
118+
col_index = base_col + col_in_code
119+
else:
120+
col_index = col_in_code
121+
return line_index + line_offset + 1, col_index + 1
96122

97123

98124
async def render_alias_command(
@@ -110,6 +136,7 @@ async def render_alias_command(
110136
last_value = None
111137
error: BaseException | None = None
112138
error_line: int | None = None
139+
error_col: int | None = None
113140

114141
pos = 0
115142
matches: list[tuple[str, re.Match[str]]] = []
@@ -134,7 +161,7 @@ async def render_alias_command(
134161
stdout_parts.append(result.stdout)
135162
if result.error:
136163
error = result.error
137-
error_line = _error_line_for_match(body, match, result.error, line_offset)
164+
error_line, error_col = _error_position_for_match(body, match, result.error, line_offset)
138165
break
139166
last_value = result.value
140167
if result.value is not None:
@@ -156,6 +183,7 @@ async def render_alias_command(
156183
error=error,
157184
last_value=last_value,
158185
error_line=error_line,
186+
error_col=error_col,
159187
)
160188

161189

src/avrae_ls/alias_tests.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class AliasTestResult:
4343
error: str | None = None
4444
details: str | None = None
4545
error_line: int | None = None
46+
error_col: int | None = None
4647

4748

4849
def discover_test_files(
@@ -161,6 +162,7 @@ async def run_alias_test(case: AliasTestCase, builder: ContextBuilder, executor:
161162
stdout=rendered.stdout,
162163
error=str(rendered.error),
163164
error_line=rendered.error_line,
165+
error_col=rendered.error_col,
164166
)
165167

166168
preview = simulate_command(rendered.command)
@@ -173,7 +175,15 @@ async def run_alias_test(case: AliasTestCase, builder: ContextBuilder, executor:
173175
error=preview.validation_error,
174176
)
175177

176-
actual = preview.preview if preview.preview is not None else rendered.last_value
178+
if preview.preview is not None:
179+
actual = preview.preview
180+
else:
181+
if rendered.command.strip() == "" and rendered.last_value is None:
182+
actual = None
183+
elif rendered.last_value is not None and rendered.command.strip() == str(rendered.last_value):
184+
actual = rendered.last_value
185+
else:
186+
actual = rendered.command
177187
embed_dict = preview.embed.to_dict() if preview.embed else None
178188

179189
if embed_dict is not None and isinstance(case.expected, dict):

tests/test_alias_tests.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22

33
from avrae_ls.alias_tests import AliasTestError, parse_alias_tests, run_alias_tests
4+
from avrae_ls.__main__ import _run_alias_tests
45
from avrae_ls.config import AvraeLSConfig
56
from avrae_ls.context import ContextBuilder
67
from avrae_ls.runtime import MockExecutor
@@ -80,6 +81,60 @@ async def test_alias_tests_include_error_line(tmp_path):
8081
assert result.error_line == 3
8182

8283

84+
@pytest.mark.asyncio
85+
async def test_alias_tests_include_error_line_with_inline_drac2_tag(tmp_path):
86+
alias_path = tmp_path / "embed-error.alias"
87+
alias_path.write_text(
88+
'!alias embed-error embed <drac2>\n# testing 123\na = 3\n# testing 456\nload_json("")\n</drac2>\n'
89+
)
90+
test_path = tmp_path / "test-embed-error.alias-test"
91+
test_path.write_text("!embed-error\n---\n\n")
92+
93+
config = AvraeLSConfig.default(tmp_path)
94+
builder = ContextBuilder(config)
95+
executor = MockExecutor(config.service)
96+
97+
case = parse_alias_tests(test_path)[0]
98+
result = (await run_alias_tests([case], builder, executor))[0]
99+
100+
assert not result.passed
101+
assert result.error is not None
102+
assert result.error_line == 5
103+
104+
105+
def test_run_tests_output_uses_rendered_command(tmp_path, capsys):
106+
(tmp_path / ".avraels.json").write_text('{"enableGvarFetch": false}')
107+
alias_path = tmp_path / "speak.alias"
108+
alias_path.write_text("!alias speak say hello {{1 + 2}}")
109+
test_path = tmp_path / "test-speak.alias-test"
110+
test_path.write_text("!speak\n---\nsay hello 4\n")
111+
112+
exit_code = _run_alias_tests(tmp_path)
113+
captured = capsys.readouterr()
114+
115+
assert exit_code == 1
116+
assert "Expected: say hello 4" in captured.out
117+
assert "Actual: say hello 3" in captured.out
118+
119+
120+
def test_run_tests_output_skips_diff_on_execution_error(tmp_path, capsys):
121+
(tmp_path / ".avraels.json").write_text('{"enableGvarFetch": false}')
122+
alias_path = tmp_path / "boom.alias"
123+
alias_path.write_text("!alias boom echo\n<drac2>\nload_json(\"\")\n</drac2>\n")
124+
test_path = tmp_path / "test-boom.alias-test"
125+
test_path.write_text("!boom\n---\nshould not compare\n")
126+
127+
exit_code = _run_alias_tests(tmp_path)
128+
captured = capsys.readouterr()
129+
130+
assert exit_code == 1
131+
assert "Execution Error" in captured.out
132+
assert "- Execution Error" not in captured.out
133+
assert "Expected:" not in captured.out
134+
assert "Actual:" not in captured.out
135+
assert "Diff:" not in captured.out
136+
137+
83138
@pytest.mark.asyncio
84139
async def test_runs_embed_alias_test(tmp_path):
85140
alias_path = tmp_path / "embedtest.alias"

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vscode-extension/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vscode-extension/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "avrae-ls-client",
33
"displayName": "Avrae Draconic Alias Language Server",
44
"description": "VS Code client for avrae-ls (draconic alias diagnostics and mock execution).",
5-
"version": "0.7.0",
5+
"version": "0.7.1",
66
"engines": {
77
"vscode": "^1.84.0"
88
},

0 commit comments

Comments
 (0)