Skip to content
Closed
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
14 changes: 10 additions & 4 deletions LSP.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,20 @@
"hint": "stippled"
},

// Show diagnostics spanning multiple lines in the view (as outlines).
// See also: "diagnostics_highlight_style".
"show_multiline_diagnostics_highlights": true,

// Gutter marker for code diagnostics.
// Valid values are "dot", "circle", "bookmark", "sign" or ""
"diagnostics_gutter_marker": "dot",

// Sort order for diagnostics in the diagnostics panel and for the Goto Diagnostic command:
// "none" - preserve order as reported from the server.
// "location" - sort by line number.
// "severity" - sort by severity (and by line number for diagnostics of the same severity).
"diagnostics_sort_order": "none",

// Show code actions:
// "annotation" - show an annotation on the right when code actions are available.
// "bulb" - show a bulb in the gutter when code actions are available.
Expand All @@ -121,10 +131,6 @@
// Show code actions in hover popup if available
"show_code_actions_in_hover": true,

// Show diagnostics spanning multiple lines in the view (as outlines).
// See also: "diagnostics_highlight_style".
"show_multiline_diagnostics_highlights": true,

// Show symbol action links in hover popup if available
"show_symbol_action_links": true,

Expand Down
33 changes: 30 additions & 3 deletions plugin/core/diagnostics_manager.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .protocol import Diagnostic, DiagnosticSeverity, DocumentUri
from .settings import userprefs
from .typing import Callable, Iterator, List, Tuple, TypeVar
from .url import parse_uri
from .views import diagnostic_severity
Expand All @@ -9,6 +10,17 @@
T = TypeVar('T')


def by_location(diagnostic: Diagnostic) -> Tuple[int, int]:
position = diagnostic.get("range", {})["start"]
return position["line"], position["character"]


def by_severity(diagnostic: Diagnostic) -> Tuple[int, int, int]:
severity = diagnostic.get("severity", DiagnosticSeverity.Hint + 1)
position = diagnostic.get("range", {})["start"]
return severity, position["line"], position["character"]


class DiagnosticsManager(OrderedDict):
# From the specs:
#
Expand All @@ -34,15 +46,29 @@ def add_diagnostics_async(self, document_uri: DocumentUri, diagnostics: List[Dia
self[uri] = diagnostics
self.move_to_end(uri) # maintain incoming order

def sorted_diagnostics(self, uri: ParsedUri) -> List[Diagnostic]:
"""
Sort diagnostics for a given URI ordered as configured by the `diagnostics_sort_order` setting.
"""
sort_order = userprefs().diagnostics_sort_order
if sort_order == "location":
return sorted(self[uri], key=by_location)
elif sort_order == "severity":
return sorted(self[uri], key=by_severity)
else: # "none"
return self[uri]

def filter_map_diagnostics_async(self, pred: Callable[[Diagnostic], bool],
f: Callable[[ParsedUri, Diagnostic], T]) -> Iterator[Tuple[ParsedUri, List[T]]]:
"""
Yields `(uri, results)` items with `results` being a list of `f(diagnostic)` for each
diagnostic for this `uri` with `pred(diagnostic) == True`, filtered by `bool(f(diagnostic))`.
Only `uri`s with non-empty `results` are returned. Each `uri` is guaranteed to be yielded
not more than once. Items and results are ordered as they came in from the server.
not more than once. Items are ordered as they came in from the server and results per item are
ordered as configured by the `diagnostics_sort_order` setting.
"""
for uri, diagnostics in self.items():
for uri in self.keys():
diagnostics = self.sorted_diagnostics(uri)
results = list(filter(None, map(functools.partial(f, uri), filter(pred, diagnostics)))) # type: List[T]
if results:
yield uri, results
Expand Down Expand Up @@ -77,8 +103,9 @@ def diagnostics_by_document_uri(self, document_uri: DocumentUri) -> List[Diagnos
def diagnostics_by_parsed_uri(self, uri: ParsedUri) -> List[Diagnostic]:
"""
Returns possibly empty list of diagnostic for `uri`.
Results are ordered as configured by the `diagnostics_sort_order` setting.
"""
return self.get(uri, [])
return self.sorted_diagnostics(uri) if uri in self else []


def severity_count(severity: int) -> Callable[[List[Diagnostic]], int]:
Expand Down
2 changes: 2 additions & 0 deletions plugin/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ class Settings:
diagnostics_gutter_marker = None # type: str
diagnostics_highlight_style = None # type: Union[str, Dict[str, str]]
diagnostics_panel_include_severity_level = None # type: int
diagnostics_sort_order = None # type: str
disabled_capabilities = None # type: List[str]
document_highlight_style = None # type: str
inhibit_snippet_completions = None # type: bool
Expand Down Expand Up @@ -227,6 +228,7 @@ def r(name: str, default: Union[bool, int, str, list, dict]) -> None:
r("diagnostics_delay_ms", 0)
r("diagnostics_gutter_marker", "dot")
r("diagnostics_panel_include_severity_level", 4)
r("diagnostics_sort_order", "none")
r("disabled_capabilities", [])
r("document_highlight_style", "underline")
r("log_debug", False)
Expand Down
14 changes: 14 additions & 0 deletions sublime-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,20 @@
"default": "dot",
"markdownDescription": "Gutter marker for code diagnostics."
},
"diagnostics_sort_order": {
"enum": [
"none",
"location",
"severity"
],
"enumDescriptions": [
"Preserve order as reported from the server.",
"Sort by line number.",
"Sort by severity (and by line number for diagnostics of the same severity)."
],
"default": "none",
"markdownDescription": "Sort order for diagnostics in the diagnostics panel and for the Goto Diagnostic command."
},
"show_code_actions": {
"enum": [
"annotation",
Expand Down