From d70137775faf34bba861078d7022993189fe3768 Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Tue, 2 Jun 2026 12:29:39 +0200 Subject: [PATCH] feat(cli): update highlighter with new nodes --- midas/cli/highlight.css | 1 + midas/cli/highlighter.py | 71 ++++++++++++++++++++++++---------------- midas/cli/hl_midas.css | 18 +++++----- midas/cli/main.py | 11 +------ 4 files changed, 52 insertions(+), 49 deletions(-) diff --git a/midas/cli/highlight.css b/midas/cli/highlight.css index 31f005d..8da787b 100644 --- a/midas/cli/highlight.css +++ b/midas/cli/highlight.css @@ -53,5 +53,6 @@ span { &.keyword { color: rgb(211, 72, 9); + pointer-events: none; } } \ No newline at end of file diff --git a/midas/cli/highlighter.py b/midas/cli/highlighter.py index c0ecea7..690c408 100644 --- a/midas/cli/highlighter.py +++ b/midas/cli/highlighter.py @@ -1,6 +1,7 @@ from __future__ import annotations from abc import ABC, abstractmethod +from dataclasses import dataclass from pathlib import Path from typing import Generic, Optional, Protocol, TextIO, TypeVar @@ -8,6 +9,7 @@ import midas.ast.midas as m import midas.ast.python as p from midas.ast.location import Location from midas.checker.diagnostic import Diagnostic +from midas.lexer.token import Token H = TypeVar("H", bound="Highlighter", contravariant=True) @@ -22,6 +24,15 @@ class Locatable(Protocol): def location(self) -> Optional[Location]: ... +@dataclass(frozen=True) +class LocatableToken: + token: Token + + @property + def location(self) -> Location: + return self.token.get_location() + + class Highlighter(ABC): BASE_CSS_PATH: Path = Path(__file__).parent / "highlight.css" EXTRA_CSS_PATH: Optional[Path] = None @@ -206,34 +217,22 @@ class PythonHighlighter( def visit_ternary_expr(self, expr: p.TernaryExpr) -> None: ... -class MidasHighlighter(Highlighter, m.Stmt.Visitor[None], m.Expr.Visitor[None]): +class MidasHighlighter( + Highlighter, m.Stmt.Visitor[None], m.Expr.Visitor[None], m.Type.Visitor[None] +): EXTRA_CSS_PATH: Optional[Path] = Path(__file__).parent / "hl_midas.css" def highlight(self, node: Highlightable[MidasHighlighter]): node.accept(self) - def visit_simple_type_stmt(self, stmt: m.SimpleTypeStmt) -> None: - self.wrap(stmt, "simple-type") - if stmt.template is not None: - stmt.template.accept(self) - stmt.base.accept(self) - if stmt.constraint is not None: - self.wrap(stmt.constraint, "constraint") - stmt.constraint.accept(self) - - def visit_complex_type_stmt(self, stmt: m.ComplexTypeStmt) -> None: - self.wrap(stmt, "complex-type") - if stmt.template is not None: - stmt.template.accept(self) - for prop in stmt.properties: - prop.accept(self) + def visit_type_stmt(self, stmt: m.TypeStmt) -> None: + self.wrap(stmt, "type-stmt") + self.wrap(LocatableToken(stmt.name), "type-name") + stmt.type.accept(self) def visit_property_stmt(self, stmt: m.PropertyStmt) -> None: self.wrap(stmt, "property") stmt.type.accept(self) - if stmt.constraint is not None: - self.wrap(stmt.constraint, "constraint") - stmt.constraint.accept(self) def visit_extend_stmt(self, stmt: m.ExtendStmt) -> None: self.wrap(stmt, "extend") @@ -243,17 +242,16 @@ class MidasHighlighter(Highlighter, m.Stmt.Visitor[None], m.Expr.Visitor[None]): def visit_op_stmt(self, stmt: m.OpStmt) -> None: self.wrap(stmt, "op") + self.wrap(LocatableToken(stmt.name), "op-name") stmt.operand.accept(self) stmt.result.accept(self) def visit_predicate_stmt(self, stmt: m.PredicateStmt) -> None: self.wrap(stmt, "predicate") + self.wrap(LocatableToken(stmt.name), "predicate-name") stmt.type.accept(self) stmt.condition.accept(self) - def visit_simple_type_expr(self, expr: m.SimpleTypeExpr) -> None: - self.wrap(expr, "simple-type-expr") - def visit_logical_expr(self, expr: m.LogicalExpr) -> None: self.wrap(expr, "logical-expr") expr.left.accept(self) @@ -282,14 +280,29 @@ class MidasHighlighter(Highlighter, m.Stmt.Visitor[None], m.Expr.Visitor[None]): def visit_wildcard_expr(self, expr: m.WildcardExpr) -> None: ... - def visit_template_expr(self, expr: m.TemplateExpr) -> None: - self.wrap(expr, "template") - expr.type.accept(self) + def visit_named_type(self, type: m.NamedType) -> None: + self.wrap(type, "named-type") - def visit_type_expr(self, expr: m.TypeExpr) -> None: - self.wrap(expr, "type") - if expr.template is not None: - expr.template.accept(self) + def visit_generic_type(self, type: m.GenericType) -> None: + self.wrap(type, "generic-type") + type.type.accept(self) + for param in type.params: + param.accept(self) + + def visit_constraint_type(self, type: m.ConstraintType) -> None: + self.wrap(type, "constraint-type") + type.type.accept(self) + type.constraint.accept(self) + + def visit_union_type(self, type: m.UnionType) -> None: + self.wrap(type, "union-type") + for type_ in type.types: + type_.accept(self) + + def visit_complex_type(self, type: m.ComplexType) -> None: + self.wrap(type, "complex-type") + for prop in type.properties: + prop.accept(self) class DiagnosticsHighlighter(Highlighter): diff --git a/midas/cli/hl_midas.css b/midas/cli/hl_midas.css index e8adef6..f5b3d1d 100644 --- a/midas/cli/hl_midas.css +++ b/midas/cli/hl_midas.css @@ -5,12 +5,12 @@ span { font-style: italic; } - &.simple-type { - --col: 108, 233, 108; - } - + &.named-type, + &.generic-type, + &.constraint-type, + &.union-type, &.complex-type { - --col: 233, 206, 108; + --col: 150, 150, 150; } &.constraint { @@ -33,10 +33,6 @@ span { --col: 193, 108, 233; } - &.simple-type-expr { - --col: 150, 150, 150; - } - &.logical-expr, &.binary-expr, &.unary-expr, @@ -48,7 +44,9 @@ span { --col: 163, 117, 71; } - &.type { + &.type-name, + &.op-name, + &.predicate-name { --col: 200, 200, 200; font-weight: bold; } diff --git a/midas/cli/main.py b/midas/cli/main.py index e683897..71635d0 100644 --- a/midas/cli/main.py +++ b/midas/cli/main.py @@ -1,7 +1,6 @@ import ast import json import logging -from dataclasses import dataclass from pathlib import Path from typing import Optional, TextIO, get_args @@ -9,7 +8,6 @@ import click import midas.ast.midas as m import midas.ast.python as p -from midas.ast.location import Location from midas.ast.printer import MidasAstPrinter, PythonAstPrinter from midas.checker.checker import Checker from midas.checker.diagnostic import Diagnostic @@ -17,6 +15,7 @@ from midas.checker.types import Type from midas.cli.highlighter import ( DiagnosticsHighlighter, Highlighter, + LocatableToken, MidasHighlighter, PythonHighlighter, ) @@ -142,14 +141,6 @@ def highlight_midas(source: str, path: str) -> Highlighter: for err in parser.errors: print(err.get_report()) - @dataclass(frozen=True) - class LocatableToken: - token: Token - - @property - def location(self) -> Location: - return self.token.get_location() - for stmt in stmts: highlighter.highlight(stmt) for token in tokens: