Passing through token reference information

This commit is contained in:
Darren Burns
2022-02-03 15:55:13 +00:00
parent 33e8bc4584
commit df6d04cb8c
5 changed files with 49 additions and 28 deletions

View File

@@ -305,7 +305,9 @@ class StylesBuilder:
try:
style = Style.parse(style_definition)
except Exception as error:
self.error(name, tokens[0], f"failed to parse style; {error}")
self.error(
name, tokens[0], f"failed to parse style {style_definition!r}; {error}"
)
if important:
self.styles.important.update(
{"text_style", "text_background", "text_color"}

View File

@@ -5,6 +5,7 @@ from functools import lru_cache
from typing import Iterator, Iterable
from rich import print
from rich.cells import cell_len
from textual.css.errors import UnresolvedVariableError
from ._styles_builder import StylesBuilder, DeclarationError
@@ -18,7 +19,7 @@ from .model import (
)
from .styles import Styles
from .tokenize import tokenize, tokenize_declarations, Token
from .tokenizer import EOFError
from .tokenizer import EOFError, ReferencedAt
SELECTOR_MAP: dict[str, tuple[SelectorType, tuple[int, int, int]]] = {
"selector": (SelectorType.TYPE, (0, 0, 1)),
@@ -260,12 +261,14 @@ def substitute_references(tokens: Iterator[Token]) -> Iterable[Token]:
reference_tokens = variables[ref_name]
variable_tokens.extend(reference_tokens)
ref_location = token.location
ref_length = token.length
ref_length = cell_len(token.value)
for token in reference_tokens:
yield token.as_reference(
location=ref_location,
length=ref_length,
yield token.ref(
ReferencedAt(
name=ref_name,
location=ref_location,
length=ref_length,
)
)
else:
raise _unresolved(
@@ -279,11 +282,14 @@ def substitute_references(tokens: Iterator[Token]) -> Iterable[Token]:
if variable_name in variables:
variable_tokens = variables[variable_name]
ref_location = token.location
ref_length = token.length
ref_length = cell_len(token.value)
for token in variable_tokens:
yield token.as_reference(
location=ref_location,
length=ref_length,
yield token.ref(
ReferencedAt(
name=variable_name,
location=ref_location,
length=ref_length,
)
)
else:
raise _unresolved(variable_name=variable_name, location=token.location)

View File

@@ -1,6 +1,5 @@
from __future__ import annotations
import sys
from dataclasses import dataclass, field
from functools import lru_cache
from typing import Any, Iterable, NamedTuple, TYPE_CHECKING
@@ -34,14 +33,10 @@ from .scalar import Scalar, ScalarOffset, Unit
from .scalar_animation import ScalarAnimation
from .transition import Transition
from .types import Display, Edge, Visibility
from .types import Specificity3, Specificity4
from .. import log
from .._animator import Animation, EasingFunction
from ..geometry import Spacing
if TYPE_CHECKING:
from ..layout import Layout
from ..dom import DOMNode

View File

@@ -6,6 +6,7 @@ import os
from typing import Iterable
import rich.repr
from rich.cells import cell_len
from rich.highlighter import ReprHighlighter
from rich.panel import Panel
from rich.text import Text
@@ -46,9 +47,22 @@ class StylesheetErrors:
append = errors.append
for rule in self.stylesheet.rules:
for token, message in rule.errors:
line_no, col_no = token.location
append(highlighter(f"{token.path or '<unknown>'}:{line_no}"))
append(self._get_snippet(token.code, line_no, col_no, token.length + 1))
if token.referenced_at:
line_no, col_no = token.referenced_at.location
append(highlighter(f"{token.path or '<unknown>'}:{line_no}"))
append(
self._get_snippet(
token.code, line_no, col_no, token.referenced_at.length + 1
)
)
else:
line_no, col_no = token.location
append(highlighter(f"{token.path or '<unknown>'}:{line_no}"))
append(
self._get_snippet(
token.code, line_no, col_no, cell_len(token.value) + 1
)
)
append(highlighter(Text(message, "red")))
append("")
return Group(*errors)

View File

@@ -39,6 +39,12 @@ class Expect:
yield from zip(self.names, self.regexes)
class ReferencedAt(NamedTuple):
name: str
location: tuple[int, int]
length: int
@rich.repr.auto
class Token(NamedTuple):
name: str
@@ -46,16 +52,16 @@ class Token(NamedTuple):
path: str
code: str
location: tuple[int, int]
length: int
referenced_at: ReferencedAt | None
def as_reference(self, location: tuple[int, int], length: int) -> "Token":
def ref(self, at: ReferencedAt | None) -> "Token":
return Token(
name=self.name,
value=self.value,
path=self.path,
code=self.code,
location=location,
length=length,
location=self.location,
referenced_at=at,
)
def __str__(self) -> str:
@@ -66,7 +72,7 @@ class Token(NamedTuple):
yield "value", self.value
yield "path", self.path
yield "location", self.location
yield "length", self.length
yield "referenced_at", self.referenced_at
class Tokenizer:
@@ -82,9 +88,7 @@ class Tokenizer:
col_no = self.col_no
if line_no >= len(self.lines):
if expect._expect_eof:
return Token(
"eof", "", self.path, self.code, (line_no, col_no), length=0
)
return Token("eof", "", self.path, self.code, (line_no, col_no), None)
else:
raise EOFError()
line = self.lines[line_no]
@@ -103,7 +107,7 @@ class Tokenizer:
break
token = Token(
name, value, self.path, self.code, (line_no, col_no), length=cell_len(value)
name, value, self.path, self.code, (line_no, col_no), referenced_at=None
)
col_no += len(value)
if col_no >= len(line):