Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for multi-location diagnostics #324

Merged
merged 2 commits into from
Apr 5, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"author": "Microsoft Corporation",
"license": "MIT",
"engines": {
"vscode": "^1.20"
"vscode": "^1.22"
},
"repository": {
"type": "git",
Expand Down
5 changes: 3 additions & 2 deletions client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import {
} from 'vscode-languageserver-protocol';

import { ColorProviderMiddleware } from './colorProvider';
import { ImplementationMiddleware } from './implementation'
import { ImplementationMiddleware } from './implementation'
import { TypeDefinitionMiddleware } from './typeDefinition';
import { ConfigurationWorkspaceMiddleware } from './configuration';
import { WorkspaceFolderWorkspaceMiddleware } from './workspaceFolders';
Expand Down Expand Up @@ -2659,7 +2659,7 @@ export abstract class BaseLanguageClient {
});
}

private _clientGetRootPath(): string | undefined{
private _clientGetRootPath(): string | undefined {
let folders = Workspace.workspaceFolders;
if (!folders || folders.length === 0) {
return undefined;
Expand Down Expand Up @@ -2904,6 +2904,7 @@ export abstract class BaseLanguageClient {
let result: ClientCapabilities = {};
ensure(result, 'workspace')!.applyEdit = true;
ensure(ensure(result, 'workspace')!, 'workspaceEdit')!.documentChanges = true;
result.diagnosticRelatedInformation = true;
for (let feature of this._features) {
feature.fillClientCapabilities(result);
}
Expand Down
9 changes: 9 additions & 0 deletions client/src/protocolConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,18 @@ export function createConverter(uriConverter?: URIConverter): Converter {
let result = new code.Diagnostic(asRange(diagnostic.range), diagnostic.message, asDiagnosticSeverity(diagnostic.severity));
if (Is.number(diagnostic.code) || Is.string(diagnostic.code)) { result.code = diagnostic.code; }
if (diagnostic.source) { result.source = diagnostic.source; }
if (diagnostic.relatedInformation) { result.relatedInformation = asRelatedInformation(diagnostic.relatedInformation); }
return result;
}

function asRelatedInformation(relatedInformation: ls.DiagnosticRelatedInformation[]): code.DiagnosticRelatedInformation[] {
return relatedInformation.map(asDiagnosticRelatedInformation);
}

function asDiagnosticRelatedInformation(information: ls.DiagnosticRelatedInformation): code.DiagnosticRelatedInformation {
return new code.DiagnosticRelatedInformation(asLocation(information.location), information.message);
}

function asPosition(value: undefined | null): undefined;
function asPosition(value: ls.Position): code.Position;
function asPosition(value: ls.Position | undefined | null): code.Position | undefined;
Expand Down
9 changes: 7 additions & 2 deletions protocol/src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
} from 'vscode-languageserver-types';

import { ImplementationRequest, ImplementationClientCapabilities, ImplementationServerCapabilities } from './protocol.implementation';
import { TypeDefinitionRequest, TypeDefinitionClientCapabilities, TypeDefinitionServerCapabilities } from './protocol.typeDefinition';
import { TypeDefinitionRequest, TypeDefinitionClientCapabilities, TypeDefinitionServerCapabilities } from './protocol.typeDefinition';
import {
WorkspaceFoldersRequest, DidChangeWorkspaceFoldersNotification, DidChangeWorkspaceFoldersParams, WorkspaceFolder,
WorkspaceFoldersChangeEvent, WorkspaceFoldersInitializeParams, WorkspaceFoldersClientCapabilities, WorkspaceFoldersServerCapabilities
Expand All @@ -28,7 +28,7 @@ import { ConfigurationRequest, ConfigurationParams, ConfigurationItem, Configura
import {
DocumentColorRequest, ColorPresentationRequest, ColorProviderOptions, DocumentColorParams, ColorPresentationParams,
Color, ColorInformation, ColorPresentation, ColorServerCapabilities, ColorClientCapabilities,
} from './protocol.colorProvider';
} from './protocol.colorProvider';

/**
* A document filter denotes a document by different properties like
Expand Down Expand Up @@ -502,6 +502,11 @@ export interface _ClientCapabilities {
*/
textDocument?: TextDocumentClientCapabilities;

/**
* Whether the client supports diagnostics with related information.
*/
diagnosticRelatedInformation?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that this property belongs here. Since diagnostics are in the form of a textDocument/publishDiagnostics request, perhaps it should go there instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I moved the capability. Thanks!


/**
* Experimental client capabilities.
*/
Expand Down
30 changes: 28 additions & 2 deletions types/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,20 @@ export interface Diagnostic {
* The diagnostic's message.
*/
message: string;

/**
* Array of information related to this diagnostic.
*/
relatedInformation?: DiagnosticRelatedInformation[];
}

/**
* Represents a supplemental information of a diagnostic, such
* as other locations that are relevant for a compiler error or warning.
*/
export interface DiagnosticRelatedInformation {
location: Location,
message: string
}

/**
Expand All @@ -215,7 +229,7 @@ export namespace Diagnostic {
/**
* Creates a new Diagnostic literal.
*/
export function create(range: Range, message: string, severity?: DiagnosticSeverity, code?: number | string, source?: string): Diagnostic {
export function create(range: Range, message: string, severity?: DiagnosticSeverity, code?: number | string, source?: string, relatedInformation?: DiagnosticRelatedInformation[]): Diagnostic {
let result: Diagnostic = { range, message };
if (Is.defined(severity)) {
result.severity = severity;
Expand All @@ -226,8 +240,12 @@ export namespace Diagnostic {
if (Is.defined(source)) {
result.source = source;
}
if (Is.defined(relatedInformation)) {
result.relatedInformation = relatedInformation;
}
return result;
}

/**
* Checks whether the given literal conforms to the [Diagnostic](#Diagnostic) interface.
*/
Expand All @@ -238,7 +256,15 @@ export namespace Diagnostic {
&& Is.string(candidate.message)
&& (Is.number(candidate.severity) || Is.undefined(candidate.severity))
&& (Is.number(candidate.code) || Is.string(candidate.code) || Is.undefined(candidate.code))
&& (Is.string(candidate.source) || Is.undefined(candidate.source));
&& (Is.string(candidate.source) || Is.undefined(candidate.source))
&& (Is.typedArray<DiagnosticRelatedInformation>(candidate.relatedInformation, isRelatedInformation) || Is.undefined(candidate.relatedInformation));
}

function isRelatedInformation(value: any): value is DiagnosticRelatedInformation {
let candidate = value as DiagnosticRelatedInformation;
return Is.defined(candidate)
&& Location.is(candidate.location)
&& Is.string(candidate.message);
}
}

Expand Down