Problems
A language server's diagnostics become problems in two places: the markers of the file in an editor, and a store of every file's problems for a problems panel.
In a file
The DiagnosticsFeature (language.diagnostics) turns the service's diagnostics into markers. A report replaces the earlier one of the same source, so two servers do not erase each other. The markers fade unused code and strike through deprecated code. The hover card lists the problems at the pointer. step and goToFirst announce the severity and message of the problem they land on.
| Member | What it does |
|---|---|
problems | The problems of the file, as Problems |
counts() | { error, warning, info } |
at(position) | The problems at a position |
step(direction) | Puts the caret on the next or previous problem, as F2 and Alt+Shift+F2 do |
goToFirst() | Puts the caret on the first problem |
onChange(listener) | Called when a report changes the problems; an edit only moves them |
useProblemCounts(language) reads counts() in a component as ProblemCounts and rerenders when it changes; null gives zeros.
function StatusBar({ language }: { language: EditorLanguage | null }) {
const counts = useProblemCounts(language);
return <span>{counts.error} errors, {counts.warning} warnings</span>;
}In the project
project.problems is a ProjectProblems store of every file's problems, for a problems panel. subscribe and getSnapshot fit useSyncExternalStore. A ProblemFile has a path and its rows; a ProblemRow has the diagnostic and the server that reported it. Rows go worst first, then in file order, and files by path. The store leaves out hints.
const files = useSyncExternalStore(project.problems.subscribe, project.problems.getSnapshot);
const counts = countsOf(files); // { error, warning, info }Without a problemSource on the host, the reports come from the service's diagnostics. A problemSource is a ProblemSource: it passes every ProblemReport (path, server, diagnostics) to its listener and returns its stop function. Use it to report files no editor holds. A report replaces the earlier one of that server for that file. serviceProblems(service, pathOf) is the default source, and new ProjectProblems(source) builds a store outside a project.
const project = new ProjectLanguage(service, {
folder,
problemSource: (listener) => backend.onDiagnostics((event) => listener({ path: event.path, server: event.server, diagnostics: event.diagnostics }))
});project.pullWorkspaceProblems(uri) asks a server for the problems of every file it knows; see the project.