diff --git a/annotations.css b/annotations.css
index e20ed8866..7481028b3 100644
--- a/annotations.css
+++ b/annotations.css
@@ -2,15 +2,15 @@
margin: 0;
border-width: 0;
}
-.lsp_annotation .errors {
+.lsp_annotation .error {
color: color(var(--redish) alpha(0.85));
}
-.lsp_annotation .warnings {
+.lsp_annotation .warning {
color: color(var(--yellowish) alpha(0.85));
}
-.lsp_annotation .info {
+.lsp_annotation .information {
color: color(var(--bluish) alpha(0.85));
}
-.lsp_annotation .hints {
+.lsp_annotation .hint {
color: color(var(--bluish) alpha(0.85));
}
diff --git a/plugin/core/constants.py b/plugin/core/constants.py
index e0e677e23..2eeb11e50 100644
--- a/plugin/core/constants.py
+++ b/plugin/core/constants.py
@@ -85,6 +85,7 @@ class RegionKey(StrEnum):
SHOW_DEFINITIONS_KEY = 'show_definitions'
# Region flags
+DIAGNOSTIC_ICON_FLAGS = sublime.RegionFlags.HIDE_ON_MINIMAP | sublime.RegionFlags.DRAW_NO_FILL | sublime.RegionFlags.DRAW_NO_OUTLINE | sublime.RegionFlags.NO_UNDO # noqa: E501
DOCUMENT_LINK_FLAGS = sublime.RegionFlags.HIDE_ON_MINIMAP | sublime.RegionFlags.DRAW_NO_FILL | sublime.RegionFlags.DRAW_NO_OUTLINE | sublime.RegionFlags.DRAW_SOLID_UNDERLINE | sublime.RegionFlags.NO_UNDO # noqa: E501
REGIONS_INITIALIZE_FLAGS = sublime.RegionFlags.HIDDEN | sublime.RegionFlags.NO_UNDO
SEMANTIC_TOKEN_FLAGS = sublime.RegionFlags.DRAW_NO_OUTLINE | sublime.RegionFlags.NO_UNDO
diff --git a/plugin/core/types.py b/plugin/core/types.py
index a0ecc6450..c0b7dce63 100644
--- a/plugin/core/types.py
+++ b/plugin/core/types.py
@@ -414,7 +414,7 @@ def diagnostics_highlight_style_flags(self) -> list[sublime.RegionFlags | None]:
flags.append(self._style_str_to_flag(user_style))
return flags
else:
- # Defaults are defined in DIAGNOSTIC_SEVERITY in plugin/core/views.py
+ # Defaults are defined in DIAGNOSTIC_STYLES in plugin/core/views.py
return [None] * 4 # default styling
diff --git a/plugin/core/views.py b/plugin/core/views.py
index 5675daa7b..afe495001 100644
--- a/plugin/core/views.py
+++ b/plugin/core/views.py
@@ -53,6 +53,7 @@
from .types import ClientConfig
from .url import parse_uri
from .workspace import is_subpath_of
+from dataclasses import dataclass
from typing import Any
from typing import Callable
from typing import cast
@@ -76,34 +77,66 @@
_baseflags = sublime.RegionFlags.DRAW_NO_FILL | sublime.RegionFlags.DRAW_NO_OUTLINE | sublime.RegionFlags.DRAW_EMPTY_AS_OVERWRITE | sublime.RegionFlags.NO_UNDO # noqa: E501
_multilineflags = sublime.RegionFlags.DRAW_NO_FILL | sublime.RegionFlags.NO_UNDO
-DIAGNOSTIC_SEVERITY: list[tuple[str, str, str, str, sublime.RegionFlags, sublime.RegionFlags]] = [
- # Kind CSS class Scope for color Icon resource add_regions flags for single-line diagnostic multi-line diagnostic # noqa: E501
- ("error", "errors", "region.redish markup.error.lsp", "Packages/LSP/icons/error.png", _baseflags | sublime.RegionFlags.DRAW_SQUIGGLY_UNDERLINE, _multilineflags), # noqa: E501
- ("warning", "warnings", "region.yellowish markup.warning.lsp", "Packages/LSP/icons/warning.png", _baseflags | sublime.RegionFlags.DRAW_SQUIGGLY_UNDERLINE, _multilineflags), # noqa: E501
- ("info", "info", "region.bluish markup.info.lsp", "Packages/LSP/icons/info.png", _baseflags | sublime.RegionFlags.DRAW_STIPPLED_UNDERLINE, _multilineflags), # noqa: E501
- ("hint", "hints", "region.bluish markup.info.hint.lsp", "", _baseflags | sublime.RegionFlags.DRAW_STIPPLED_UNDERLINE, _multilineflags), # noqa: E501
-]
+
+@dataclass
+class DiagnosticStyle:
+ kind: str
+ css_class: str
+ region_scope: str
+ icon_resource: str
+ single_line_region_flags: sublime.RegionFlags
+ multi_line_region_flags: sublime.RegionFlags
+
+
+DIAGNOSTIC_STYLES: dict[DiagnosticSeverity, DiagnosticStyle] = {
+ DiagnosticSeverity.Error: DiagnosticStyle(
+ 'error',
+ 'error',
+ 'region.redish markup.error.lsp',
+ 'Packages/LSP/icons/error.png',
+ _baseflags | sublime.RegionFlags.DRAW_SQUIGGLY_UNDERLINE,
+ _multilineflags
+ ),
+ DiagnosticSeverity.Warning: DiagnosticStyle(
+ 'warning',
+ 'warning',
+ 'region.yellowish markup.warning.lsp',
+ 'Packages/LSP/icons/warning.png',
+ _baseflags | sublime.RegionFlags.DRAW_SQUIGGLY_UNDERLINE,
+ _multilineflags
+ ),
+ DiagnosticSeverity.Information: DiagnosticStyle(
+ 'info',
+ 'information',
+ 'region.bluish markup.info.lsp',
+ 'Packages/LSP/icons/info.png',
+ _baseflags | sublime.RegionFlags.DRAW_STIPPLED_UNDERLINE,
+ _multilineflags
+ ),
+ DiagnosticSeverity.Hint: DiagnosticStyle(
+ 'hint',
+ 'hint',
+ 'region.bluish markup.info.hint.lsp',
+ '',
+ _baseflags | sublime.RegionFlags.DRAW_STIPPLED_UNDERLINE,
+ _multilineflags
+ ),
+}
class DiagnosticSeverityData:
- __slots__ = ('regions', 'regions_with_tag', 'annotations', 'scope', 'icon')
+ __slots__ = ('regions', 'regions_with_tag', 'annotations')
- def __init__(self, severity: int) -> None:
+ def __init__(self) -> None:
self.regions: list[sublime.Region] = []
self.regions_with_tag: dict[DiagnosticTag, list[sublime.Region]] = {}
self.annotations: list[str] = []
- _, _, self.scope, self.icon, _, _ = DIAGNOSTIC_SEVERITY[severity - 1]
- if userprefs().diagnostics_gutter_marker != "sign":
- self.icon = "" if severity == DiagnosticSeverity.Hint else userprefs().diagnostics_gutter_marker
class InvalidUriSchemeException(Exception):
def __init__(self, uri: str) -> None:
- self.uri = uri
-
- def __str__(self) -> str:
- return f"invalid URI scheme: {self.uri}"
+ super().__init__(f"invalid URI scheme: {uri}")
def get_line(window: sublime.Window, file_name: str, row: int, strip: bool = True) -> str:
@@ -698,16 +731,17 @@ def document_color_params(view: sublime.View) -> DocumentColorParams:
return {"textDocument": text_document_identifier(view)}
-def format_severity(severity: int) -> str:
- if 1 <= severity <= len(DIAGNOSTIC_SEVERITY):
- return DIAGNOSTIC_SEVERITY[severity - 1][0]
- return "???"
-
-
def diagnostic_severity(diagnostic: Diagnostic) -> DiagnosticSeverity:
return diagnostic.get("severity", DiagnosticSeverity.Error)
+def diagnostic_icon(severity: DiagnosticSeverity) -> str:
+ if userprefs().diagnostics_gutter_marker == "sign":
+ return DIAGNOSTIC_STYLES[severity].icon_resource
+ else:
+ return "" if severity == DiagnosticSeverity.Hint else userprefs().diagnostics_gutter_marker
+
+
def format_diagnostics_for_annotation(diagnostics: list[Diagnostic], css_class: str) -> list[str]:
annotations = []
for diagnostic in diagnostics:
@@ -735,7 +769,7 @@ def format_diagnostic_for_panel(diagnostic: Diagnostic) -> tuple[str, int | None
result = " {:>4}:{:<4}{:<8}{}".format(
diagnostic["range"]["start"]["line"] + 1,
diagnostic["range"]["start"]["character"] + 1,
- format_severity(diagnostic_severity(diagnostic)),
+ DIAGNOSTIC_STYLES[diagnostic_severity(diagnostic)].kind,
lines[0]
)
if formatted != "" or code is not None:
@@ -851,7 +885,7 @@ def format_diagnostic_for_html(config: ClientConfig, diagnostic: Diagnostic, bas
if related_infos := diagnostic.get("relatedInformation"):
info = "
".join(_format_diagnostic_related_info(config, info, base_dir) for info in related_infos)
html += '
' + _html_element("pre", info, class_name="related_info", escape=False)
- severity_class = DIAGNOSTIC_SEVERITY[diagnostic_severity(diagnostic) - 1][1]
+ severity_class = DIAGNOSTIC_STYLES[diagnostic_severity(diagnostic)].css_class
return _html_element("pre", html, class_name=severity_class, escape=False)
diff --git a/plugin/diagnostics.py b/plugin/diagnostics.py
index 267b738ca..501a14074 100644
--- a/plugin/diagnostics.py
+++ b/plugin/diagnostics.py
@@ -12,8 +12,8 @@
from .core.settings import userprefs
from .core.types import DocumentSelector_
from .core.url import normalize_uri
-from .core.views import DIAGNOSTIC_SEVERITY
from .core.views import diagnostic_severity
+from .core.views import DIAGNOSTIC_STYLES
from .core.views import format_diagnostics_for_annotation
from typing import Union
import itertools
@@ -141,7 +141,7 @@ def draw(self, diagnostics: list[tuple[Diagnostic, sublime.Region]]) -> None:
continue
matching_diagnostics[0].append(diagnostic)
matching_diagnostics[1].append(region)
- css_class = DIAGNOSTIC_SEVERITY[severity - 1][1]
+ css_class = DIAGNOSTIC_STYLES[severity].css_class
annotations = format_diagnostics_for_annotation(matching_diagnostics[0], css_class)
color = self._severity_colors[severity]
self._view.add_regions(
diff --git a/plugin/session_buffer.py b/plugin/session_buffer.py
index 1ccab23f3..6b5e35a6a 100644
--- a/plugin/session_buffer.py
+++ b/plugin/session_buffer.py
@@ -3,6 +3,7 @@
from ..protocol import CodeLens
from ..protocol import ColorInformation
from ..protocol import Diagnostic
+from ..protocol import DiagnosticSeverity
from ..protocol import DiagnosticTag
from ..protocol import DocumentDiagnosticParams
from ..protocol import DocumentDiagnosticReport
@@ -158,7 +159,7 @@ def __init__(self, session_view: SessionViewProtocol, buffer_id: int, uri: Docum
self._pending_changes: PendingChanges | None = None
self.pending_refreshes: RequestFlags = RequestFlags.NONE
self._diagnostics: list[tuple[Diagnostic, sublime.Region]] = []
- self.diagnostics_data_per_severity: dict[tuple[int, bool], DiagnosticSeverityData] = {}
+ self.diagnostics_data_per_severity: dict[tuple[DiagnosticSeverity, bool], DiagnosticSeverityData] = {}
self._diagnostics_versions: dict[DiagnosticsIdentifier, int] = {}
self.diagnostics_flags = 0
self._diagnostics_are_visible = False
@@ -694,14 +695,14 @@ def on_diagnostics_async(
return
diagnostics_version = version
diagnostics: list[tuple[Diagnostic, sublime.Region]] = []
- data_per_severity: dict[tuple[int, bool], DiagnosticSeverityData] = {}
+ data_per_severity: dict[tuple[DiagnosticSeverity, bool], DiagnosticSeverityData] = {}
for diagnostic in raw_diagnostics:
region = range_to_region(diagnostic["range"], view)
severity = diagnostic_severity(diagnostic)
key = (severity, len(view.split_by_newlines(region)) > 1)
data = data_per_severity.get(key)
if data is None:
- data = DiagnosticSeverityData(severity)
+ data = DiagnosticSeverityData()
data_per_severity[key] = data
if tags := diagnostic.get('tags', []):
for tag in tags:
diff --git a/plugin/session_view.py b/plugin/session_view.py
index b04bfafa3..08e3f44c9 100644
--- a/plugin/session_view.py
+++ b/plugin/session_view.py
@@ -1,9 +1,11 @@
from __future__ import annotations
from ..protocol import Command
+from ..protocol import DiagnosticSeverity
from ..protocol import DocumentHighlightKind
from ..protocol import DocumentUri
from .core.active_request import ActiveRequest
+from .core.constants import DIAGNOSTIC_ICON_FLAGS
from .core.constants import DIAGNOSTIC_TAG_SCOPES
from .core.constants import HOVER_ENABLED_KEY
from .core.constants import RegionKey
@@ -16,7 +18,8 @@
from .core.sessions import Session
from .core.settings import userprefs
from .core.views import ChangeEventAction
-from .core.views import DIAGNOSTIC_SEVERITY
+from .core.views import diagnostic_icon
+from .core.views import DIAGNOSTIC_STYLES
from .core.views import document_highlight_key
from .core.views import make_command_link
from .core.views import range_to_region
@@ -94,7 +97,7 @@ def on_before_remove(self) -> None:
self.session.cancel_request_async(request_id)
self.session.unregister_session_view_async(self)
self.session.config.erase_view_status(self.view)
- for severity in reversed(range(1, len(DIAGNOSTIC_SEVERITY) + 1)):
+ for severity in reversed(DIAGNOSTIC_STYLES.keys()):
self.view.erase_regions(f"{self.diagnostics_key(severity, False)}_icon")
self.view.erase_regions(f"{self.diagnostics_key(severity, False)}_underline")
self.view.erase_regions(f"{self.diagnostics_key(severity, True)}_icon")
@@ -294,7 +297,7 @@ def shutdown_async(self) -> None:
if listener := self.listener():
listener.on_session_shutdown_async(self.session)
- def diagnostics_key(self, severity: int, multiline: bool) -> str:
+ def diagnostics_key(self, severity: DiagnosticSeverity, multiline: bool) -> str:
return "lsp{}d{}{}".format(self.session.config.name, "m" if multiline else "s", severity)
def present_diagnostics_async(self, is_view_visible: bool) -> None:
@@ -306,19 +309,18 @@ def _redraw_diagnostics_async(self) -> None:
flags = userprefs().diagnostics_highlight_style_flags() # for single lines
multiline_flags = None if userprefs().show_multiline_diagnostics_highlights else sublime.RegionFlags.DRAW_NO_FILL | sublime.RegionFlags.DRAW_NO_OUTLINE | sublime.RegionFlags.NO_UNDO # noqa: E501
level = userprefs().show_diagnostics_severity_level
- for sev in reversed(range(1, len(DIAGNOSTIC_SEVERITY) + 1)):
- self._draw_diagnostics(sev, level, flags[sev - 1] or DIAGNOSTIC_SEVERITY[sev - 1][4], multiline=False)
- self._draw_diagnostics(sev, level, multiline_flags or DIAGNOSTIC_SEVERITY[sev - 1][5], multiline=True)
+ for sev, style in reversed(DIAGNOSTIC_STYLES.items()):
+ self._draw_diagnostics(sev, level, flags[sev - 1] or style.single_line_region_flags, multiline=False)
+ self._draw_diagnostics(sev, level, multiline_flags or style.multi_line_region_flags, multiline=True)
self._diagnostic_annotations.draw(self.session_buffer.diagnostics)
def _draw_diagnostics(
self,
- severity: int,
+ severity: DiagnosticSeverity,
max_severity_level: int,
flags: sublime.RegionFlags,
multiline: bool
) -> None:
- ICON_FLAGS = sublime.RegionFlags.HIDE_ON_MINIMAP | sublime.RegionFlags.DRAW_NO_FILL | sublime.RegionFlags.DRAW_NO_OUTLINE | sublime.RegionFlags.NO_UNDO # noqa: E501
key = self.diagnostics_key(severity, multiline)
tags = {tag: TagData(f'{key}_tags_{tag}') for tag in DIAGNOSTIC_TAG_SCOPES}
data = self._session_buffer.diagnostics_data_per_severity.get((severity, multiline))
@@ -332,8 +334,10 @@ def _draw_diagnostics(
tags[tag].scope = tag_scope
else:
non_tag_regions.extend(regions)
- self.view.add_regions(f"{key}_icon", non_tag_regions, data.scope, data.icon, ICON_FLAGS)
- self.view.add_regions(f"{key}_underline", non_tag_regions, data.scope, "", flags)
+ region_scope = DIAGNOSTIC_STYLES[severity].region_scope
+ icon = diagnostic_icon(severity)
+ self.view.add_regions(f"{key}_icon", non_tag_regions, region_scope, icon, DIAGNOSTIC_ICON_FLAGS)
+ self.view.add_regions(f"{key}_underline", non_tag_regions, region_scope, "", flags)
else:
self.view.erase_regions(f"{key}_icon")
self.view.erase_regions(f"{key}_underline")
diff --git a/popups.css b/popups.css
index e323d300e..78bbe4e2c 100644
--- a/popups.css
+++ b/popups.css
@@ -36,30 +36,25 @@
margin-bottom: 0.5rem;
font-family: var(--mdpopups-font-mono);
}
-.errors {
+.error,
+.warning,
+.information,
+.hint {
border-width: 0;
- background-color: color(var(--redish) alpha(0.25));
color: var(--foreground);
padding: 0.5rem;
- white-space: pre-wrap;
}
-.warnings {
- border-width: 0;
+.error {
+ background-color: color(var(--redish) alpha(0.25));
+}
+.warning {
background-color: color(var(--yellowish) alpha(0.25));
- color: var(--foreground);
- padding: 0.5rem;
}
-.info {
- border-width: 0;
+.information {
background-color: color(var(--bluish) alpha(0.25));
- color: var(--foreground);
- padding: 0.5rem;
}
-.hints {
- border-width: 0;
+.hint {
background-color: color(var(--bluish) alpha(0.25));
- color: var(--foreground);
- padding: 0.5rem;
}
.actions, .code-actions {
font-family: system;