Skip to content

Commit

Permalink
feat(diagnostic): add showRelatedInformation (#5090)
Browse files Browse the repository at this point in the history
  • Loading branch information
hexh250786313 authored Jul 22, 2024
1 parent 33d0a52 commit bf68721
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 94 deletions.
12 changes: 6 additions & 6 deletions data/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1039,12 +1039,6 @@
"description": "Enable diagnostic refresh on insert mode, default false.",
"default": false
},
"diagnostic.separateRelatedInformationAsDiagnostics": {
"type": "boolean",
"default": false,
"scope": "application",
"description": "Separate related information as diagnostics."
},
"diagnostic.showDeprecated": {
"type": "boolean",
"default": true,
Expand Down Expand Up @@ -1139,6 +1133,12 @@
"description": "Text of warning sign",
"default": ""
},
"diagnostic.showRelatedInformation": {
"type": "boolean",
"default": true,
"scope": "language-overridable",
"description": "Display related information in the diagnostic floating window."
},
"dialog.confirmKey": {
"type": "string",
"default": "<cr>",
Expand Down
12 changes: 6 additions & 6 deletions doc/coc-config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,6 @@ Diagnostic~

Scope: `language-overridable`, default: `false`

"diagnostic.separateRelatedInformationAsDiagnostics" *coc-config-diagnostic-separateRelatedInformationAsDiagnostics*

Separate related information as diagnostics.

Scope: `application`, default: `false`

"diagnostic.showDeprecated" *coc-config-diagnostic-showDeprecated*

Show diagnostics with deprecated tag.
Expand Down Expand Up @@ -371,6 +365,12 @@ Diagnostic~

Scope: `application`, default: `""`

"diagnostic.showRelatedInformation" *coc-config-diagnostic-showRelatedInformation*

Display related information in the diagnostic floating window.

Scope: `language-overridable`, default: `true`

------------------------------------------------------------------------------
Dialog~
*coc-config-dialog*
Expand Down
45 changes: 0 additions & 45 deletions src/__tests__/client/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -598,51 +598,6 @@ describe('Client integration', () => {
expect(fn).toBeCalled()
})

it('should separate diagnostics', async () => {
async function startServer(disable?: boolean, handleDiagnostics?: (uri: string, diagnostics: Diagnostic[], next: HandleDiagnosticsSignature) => void): Promise<lsclient.LanguageClient> {
let clientOptions: lsclient.LanguageClientOptions = {
disableDiagnostics: disable,
separateDiagnostics: true,
initializationOptions: {},
middleware: {
handleDiagnostics
}
}
let serverModule = path.join(__dirname, './server/eventServer.js')
let serverOptions: lsclient.ServerOptions = {
module: serverModule,
transport: lsclient.TransportKind.stdio,
}
let client = new lsclient.LanguageClient('html', 'Test Language Server', serverOptions, clientOptions)
await client.start()
return client
}
let client = await startServer()
await client.sendNotification('diagnostics')
await helper.waitValue(() => {
let collection = client.diagnostics
let res = collection.get('lsptest:/2')
return res.length
}, 2)
await client.stop()
client = await startServer(true)
await client.sendNotification('diagnostics')
await helper.wait(50)
let collection = client.diagnostics
expect(collection).toBeUndefined()
await client.stop()
let called = false
client = await startServer(false, (uri, diagnostics, next) => {
called = true
next(uri, diagnostics)
})
await client.sendNotification('diagnostics')
await helper.waitValue(() => {
return called
}, true)
await client.stop()
})

it('should check version on apply workspaceEdit', async () => {
let uri = URI.file(__filename)
await workspace.loadFile(uri.toString())
Expand Down
25 changes: 22 additions & 3 deletions src/diagnostic/buffer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict'
import type { Buffer, Neovim, VirtualTextOption } from '@chemzqm/neovim'
import { Diagnostic, DiagnosticSeverity, Position, TextEdit } from 'vscode-languageserver-types'
import { URI } from 'vscode-uri'
import events from '../events'
import { SyncItem } from '../model/bufferSync'
import Document from '../model/document'
Expand All @@ -10,6 +11,7 @@ import { isFalsyOrEmpty } from '../util/array'
import { lineInRange, positionInRange } from '../util/position'
import { Emitter, Event } from '../util/protocol'
import window from '../window'
import { path } from '../util/node'
import workspace from '../workspace'
import { adjustDiagnostics, DiagnosticConfig, formatDiagnostic, getHighlightGroup, getLocationListItem, getNameFromSeverity, getSeverityType, LocationListItem, severityLevel, sortDiagnostics } from './util'
import { stripAnsiColoring } from '../util/ansiparse'
Expand Down Expand Up @@ -124,6 +126,7 @@ export class DiagnosticBuffer implements SyncItem {
showUnused: config.get<boolean>('showUnused', true),
showDeprecated: config.get<boolean>('showDeprecated', true),
format: config.get<string>('format', '[%source%code] [%severity] %message'),
showRelatedInformation: config.get<boolean>('showRelatedInformation', true),
}
if (this._config.virtualText && !virtualTextSrcId) {
void this.nvim.createNamespace('coc-diagnostic-virtualText').then(id => {
Expand Down Expand Up @@ -352,9 +355,25 @@ export class DiagnosticBuffer implements SyncItem {
} else {
filetype = ft
}
docs.push({ filetype, content: formatDiagnostic(config.format, diagnostic) })
if (diagnostic.codeDescription?.href) {
docs.push({ filetype: 'txt', content: diagnostic.codeDescription.href })
let msg = diagnostic.message
let link = diagnostic.codeDescription?.href ?? ''
if (config.showRelatedInformation && diagnostic.relatedInformation?.length) {
msg = `${diagnostic.message}\n\nRelated information:\n`
for (const info of diagnostic.relatedInformation) {
const fsPath = URI.parse(info.location.uri).fsPath
const basename = path.basename(fsPath)
const line = info.location.range.start.line + 1
const column = info.location.range.start.character + 1
msg = `${msg}\n * ${basename}#${line},${column}: ${info.message}`
}
msg = msg + "\n\n"
}
docs.push({ filetype, content: formatDiagnostic(config.format, {
...diagnostic,
message: msg
}) })
if (link) {
docs.push({ filetype: 'txt', content: link })
}
})
await floatFactory.show(docs, this.config.floatConfig)
Expand Down
11 changes: 8 additions & 3 deletions src/diagnostic/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,7 @@ class DiagnosticManager implements Disposable {
}

public async jumpRelated(): Promise<void> {
let diagnostics = await this.getCurrentDiagnostics()
let diagnostic = diagnostics.find(o => o.relatedInformation != null)
let locations = diagnostic ? diagnostic.relatedInformation.map(o => o.location) : []
let locations = await this.relatedInformation()
if (locations.length == 1) {
await workspace.jumpTo(locations[0].uri, locations[0].range.start)
} else if (locations.length > 1) {
Expand All @@ -443,6 +441,13 @@ class DiagnosticManager implements Disposable {
}
}

public async relatedInformation(): Promise<Location[]> {
let diagnostics = await this.getCurrentDiagnostics()
let diagnostic = diagnostics.find(o => o.relatedInformation != null)
let locations = diagnostic ? diagnostic.relatedInformation.map(o => o.location) : []
return locations
}

public reset(): void {
clearTimeout(this.messageTimer)
this.buffers.reset()
Expand Down
1 change: 1 addition & 0 deletions src/diagnostic/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export interface DiagnosticConfig {
showDeprecated: boolean
format: string
floatConfig: FloatConfig
showRelatedInformation: boolean
}

export function formatDiagnostic(format: string, diagnostic: Diagnostic): string {
Expand Down
32 changes: 1 addition & 31 deletions src/language-client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ export type LanguageClientOptions = {
rootPatterns?: string[]
requireRootPattern?: boolean
documentSelector?: DocumentSelector
separateDiagnostics?: boolean
disableMarkdown?: boolean
disableWorkspaceFolders?: boolean
disableDiagnostics?: boolean
Expand Down Expand Up @@ -206,7 +205,6 @@ type ResolvedClientOptions = {
disabledFeatures: string[]
disableMarkdown: boolean
disableDynamicRegister: boolean
separateDiagnostics: boolean
rootPatterns?: string[]
requireRootPattern?: boolean
documentSelector: DocumentSelector
Expand Down Expand Up @@ -382,15 +380,10 @@ export abstract class BaseLanguageClient implements FeatureClient<Middleware, La
}
}
}
let separateDiagnostics = clientOptions.separateDiagnostics
if (clientOptions.separateDiagnostics === undefined) {
separateDiagnostics = workspace.getConfiguration('diagnostic', clientOptions.workspaceFolder).get('separateRelatedInformationAsDiagnostics') as boolean
}
return {
disabledFeatures,
disableMarkdown,
disableSnippetCompletion,
separateDiagnostics,
diagnosticPullOptions: pullOption,
rootPatterns: clientOptions.rootPatterns ?? [],
requireRootPattern: clientOptions.requireRootPattern,
Expand Down Expand Up @@ -1575,30 +1568,7 @@ export abstract class BaseLanguageClient implements FeatureClient<Middleware, La
private setDiagnostics(uri: string, diagnostics: Diagnostic[] | undefined) {
if (!this._diagnostics) return

const separate = this.clientOptions.separateDiagnostics
// TODO make is async
if (separate && diagnostics.length > 0) {
const entries: Map<string, Diagnostic[]> = new Map()
entries.set(uri, diagnostics)
for (const diagnostic of diagnostics) {
if (diagnostic.relatedInformation?.length) {
let message = `${diagnostic.message}\n\nRelated diagnostics:\n`
for (const info of diagnostic.relatedInformation) {
const basename = path.basename(URI.parse(info.location.uri).fsPath)
const ln = info.location.range.start.line
message = `${message}\n${basename}(line ${ln + 1}): ${info.message}`

const diags: Diagnostic[] = entries.get(info.location.uri) || []
diags.push(Diagnostic.create(info.location.range, info.message, DiagnosticSeverity.Hint, diagnostic.code, diagnostic.source))
entries.set(info.location.uri, diags)
}
diagnostic.message = message
}
this._diagnostics.set(Array.from(entries))
}
} else {
this._diagnostics.set(uri, diagnostics)
}
this._diagnostics.set(uri, diagnostics)
}

private handleApplyWorkspaceEdit(params: ApplyWorkspaceEditParams): Promise<ApplyWorkspaceEditResult> {
Expand Down
1 change: 1 addition & 0 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export default class Plugin {
this.addAction('diagnosticPrevious', severity => diagnosticManager.jumpPrevious(severity))
this.addAction('diagnosticPreview', () => diagnosticManager.preview())
this.addAction('diagnosticList', () => diagnosticManager.getDiagnosticList())
this.addAction('diagnosticRelatedInformation', () => diagnosticManager.relatedInformation())
this.addAction('findLocations', (id, method, params, openCommand) => this.handler.locations.findLocations(id, method, params, openCommand))
this.addAction('getTagList', () => this.handler.locations.getTagList())
this.addAction('definitions', () => this.handler.locations.definitions())
Expand Down

0 comments on commit bf68721

Please sign in to comment.