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

Add support for InlayHint.TextEdits #5177

Merged
merged 6 commits into from
May 20, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
gulp test
npm run test:artifacts
env:
CODE_VERSION: 1.65.0
CODE_VERSION: 1.66.0
DISPLAY: :99.0

- name: Build platform-specific extension package
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
* coreclr debug configuration should support input variables for envFile ([#5102](https://github.com/OmniSharp/omnisharp-vscode/issues/5102), PR: [#5189](https://github.com/OmniSharp/omnisharp-vscode/pull/5189))
* Fix small spelling mistake (PR: [#5215](https://github.com/OmniSharp/omnisharp-vscode/pull/5215))
* Low-hanging nullable fruit (PR: [#5186](https://github.com/OmniSharp/omnisharp-vscode/pull/5186))
* Fire a buffer update instead of filechanged when active editor changes ([#5216](https://github.com/OmniSharp/omnisharp-vscode/issues/5216), PR: [#5218](https://github.com/OmniSharp/omnisharp-vscode/pull/5218))
* Add support for InlayHint.TextEdits (PR: [#5177](https://github.com/OmniSharp/omnisharp-vscode/pull/5177))
* Fix .net6 OmniSharp acquisition on Linux arm64 (PR: [#5172](https://github.com/OmniSharp/omnisharp-vscode/pull/5172))
* Remove project.json reference in debugger.md (PR: [#5210](https://github.com/OmniSharp/omnisharp-vscode/pull/5210))
* Update debugger to 1.24.5 (PR: [#5211](https://github.com/OmniSharp/omnisharp-vscode/pull/5211))
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ See issue [#5120](https://github.com/OmniSharp/omnisharp-vscode/issues/5120) for
* coreclr debug configuration should support input variables for envFile ([#5102](https://github.com/OmniSharp/omnisharp-vscode/issues/5102), PR: [#5189](https://github.com/OmniSharp/omnisharp-vscode/pull/5189))
* Fix small spelling mistake (PR: [#5215](https://github.com/OmniSharp/omnisharp-vscode/pull/5215))
* Low-hanging nullable fruit (PR: [#5186](https://github.com/OmniSharp/omnisharp-vscode/pull/5186))
* Fire a buffer update instead of filechanged when active editor changes ([#5216](https://github.com/OmniSharp/omnisharp-vscode/issues/5216), PR: [#5218](https://github.com/OmniSharp/omnisharp-vscode/pull/5218))
* Add support for InlayHint.TextEdits (PR: [#5177](https://github.com/OmniSharp/omnisharp-vscode/pull/5177))
* Fix .net6 OmniSharp acquisition on Linux arm64 (PR: [#5172](https://github.com/OmniSharp/omnisharp-vscode/pull/5172))
* Remove project.json reference in debugger.md (PR: [#5210](https://github.com/OmniSharp/omnisharp-vscode/pull/5210))
* Update debugger to 1.24.5 (PR: [#5211](https://github.com/OmniSharp/omnisharp-vscode/pull/5211))
Expand Down
19 changes: 10 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"@types/semver": "5.5.0",
"@types/tmp": "0.0.33",
"@types/unzipper": "^0.9.1",
"@types/vscode": "1.65.0",
"@types/vscode": "1.66.0",
"@types/yauzl": "2.9.1",
"@vscode/test-electron": "2.1.3",
"archiver": "5.3.0",
Expand Down Expand Up @@ -576,7 +576,7 @@
}
],
"engines": {
"vscode": "^1.65.0"
"vscode": "^1.66.0"
},
"activationEvents": [
"onDebugInitialConfigurations",
Expand Down
19 changes: 12 additions & 7 deletions src/features/inlayHintProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import AbstractProvider from './abstractProvider';
import { OmniSharpServer } from '../omnisharp/server';
import { LanguageMiddlewareFeature } from '../omnisharp/LanguageMiddlewareFeature';
import CompositeDisposable from '../CompositeDisposable';
import { InlayHint, InlayHintRequest, InlayHintResolve as InlayHintResolveRequest } from '../omnisharp/protocol';
import { fromVSCodeRange, toVSCodePosition } from '../omnisharp/typeConversion';
import { InlayHint, InlayHintRequest, InlayHintResolve as InlayHintResolveRequest, LinePositionSpanTextChange } from '../omnisharp/protocol';
import { fromVSCodeRange, toVSCodePosition, toVSCodeTextEdit } from '../omnisharp/typeConversion';
import { isVirtualCSharpDocument } from './virtualDocumentTracker';

export default class CSharpInlayHintProvider extends AbstractProvider implements vscode.InlayHintsProvider {
Expand All @@ -34,7 +34,7 @@ export default class CSharpInlayHintProvider extends AbstractProvider implements
if (document.uri.scheme !== "file") {
return [];
}

if (isVirtualCSharpDocument(document)) {
return [];
}
Expand All @@ -50,7 +50,7 @@ export default class CSharpInlayHintProvider extends AbstractProvider implements
const hints = await serverUtils.getInlayHints(this._server, request, token);

return hints.InlayHints.map((inlayHint): vscode.InlayHint => {
const mappedHint = this.toVscodeHint(inlayHint);
const mappedHint = this.toVSCodeHint(inlayHint);
this._hintsMap.set(mappedHint, inlayHint);
return mappedHint;
});
Expand All @@ -68,17 +68,22 @@ export default class CSharpInlayHintProvider extends AbstractProvider implements

try {
const result = await serverUtils.resolveInlayHints(this._server, request, token);
return this.toVscodeHint(result);
return this.toVSCodeHint(result);
} catch (error) {
return Promise.reject(`Problem invoking 'ResolveInlayHints' on OmniSharpServer: ${error}`);
}
}

private toVscodeHint(inlayHint: InlayHint): vscode.InlayHint {
private toVSCodeHint(inlayHint: InlayHint): vscode.InlayHint {
return {
label: inlayHint.Label,
position: toVSCodePosition(inlayHint.Position),
tooltip: new vscode.MarkdownString(inlayHint.Tooltip ?? "")
tooltip: new vscode.MarkdownString(inlayHint.Tooltip ?? ""),
textEdits: toVSCodeTextEdits(inlayHint.TextEdits),
};

function toVSCodeTextEdits(textEdits: LinePositionSpanTextChange[]): vscode.TextEdit[] {
return textEdits ? textEdits.map(toVSCodeTextEdit) : undefined;
}
}
}
1 change: 1 addition & 0 deletions src/omnisharp/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ export interface InlayHint {
Label: string;
Tooltip?: string;
Data: any;
TextEdits?: LinePositionSpanTextChange[];
}

export interface InlayHintResponse {
Expand Down
27 changes: 24 additions & 3 deletions src/omnisharp/typeConversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,28 @@ export function toVSCodePosition(point: protocol.V2.Point): vscode.Position {
return new vscode.Position(point.Line, point.Column);
}

export function createRequest<T extends protocol.Request>(document: vscode.TextDocument, where: vscode.Position, includeBuffer: boolean = false): T {
export function toVSCodeTextEdit(textChange: protocol.LinePositionSpanTextChange): vscode.TextEdit {
return new vscode.TextEdit(toVSCodeRange(textChange), textChange.NewText);

function toVSCodeRange(textChange: protocol.LinePositionSpanTextChange): vscode.Range {
333fred marked this conversation as resolved.
Show resolved Hide resolved
const newStart = new vscode.Position(textChange.StartLine, textChange.StartColumn);
const newEnd = new vscode.Position(textChange.EndLine, textChange.EndColumn);
return new vscode.Range(newStart, newEnd);
}
}

export function createRequest<T extends protocol.Request>(document: vscode.TextDocument, where: vscode.Position | vscode.Range, includeBuffer: boolean = false): T {

let Line: number, Column: number;

if (where instanceof vscode.Position) {
Line = where.line;
Column = where.character;
} else if (where instanceof vscode.Range) {
Line = where.start.line;
Column = where.start.character;
}

// for metadata sources, we need to remove the [metadata] from the filename, and prepend the $metadata$ authority
// this is expected by the Omnisharp server to support metadata-to-metadata navigation
const fileName = document.uri.scheme === "omnisharp-metadata" ?
Expand All @@ -72,8 +93,8 @@ export function createRequest<T extends protocol.Request>(document: vscode.TextD
const request: protocol.Request = {
FileName: fileName,
Buffer: includeBuffer ? document.getText() : undefined,
Line: where.line,
Column: where.character,
Line: Line,
Column: Column,
};

return <T>request;
Expand Down
50 changes: 37 additions & 13 deletions test/integrationTests/inlayHints.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { should, assert } from 'chai';
import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator, restartOmniSharpServer } from './integrationHelpers';
import testAssetWorkspace from './testAssets/testAssetWorkspace';
import * as path from 'path';
import { InlayHint, LinePositionSpanTextChange } from '../../src/omnisharp/protocol';

const chai = require('chai');
chai.use(require('chai-arrays'));
Expand Down Expand Up @@ -49,7 +50,7 @@ suite(`Inlay Hints ${testAssetWorkspace.description}`, function () {
const projectDirectory = testAssetWorkspace.projects[0].projectDirectoryPath;
const filePath = path.join(projectDirectory, fileName);
fileUri = vscode.Uri.file(filePath);

await vscode.commands.executeCommand("vscode.open", fileUri);
await testAssetWorkspace.waitForIdle(activation.eventStream);
});
Expand All @@ -60,19 +61,42 @@ suite(`Inlay Hints ${testAssetWorkspace.description}`, function () {

test("Hints retrieved for region", async () => {
const range = new vscode.Range(new vscode.Position(4, 8), new vscode.Position(15, 85));
const hints : vscode.InlayHint[] = await vscode.commands.executeCommand('vscode.executeInlayHintProvider', fileUri, range);
const hints: vscode.InlayHint[] = await vscode.commands.executeCommand('vscode.executeInlayHintProvider', fileUri, range);

assert.lengthOf(hints, 6);
assertValues(hints[0], 'InlayHints ', 6, 12);
assertValues(hints[1], ' InlayHints', 7, 27);
assertValues(hints[2], 'string ', 8, 28);
assertValues(hints[3], 'i: ', 9, 17);
assertValues(hints[4], 'param1: ', 10, 15);
assertValues(hints[5], 'param1: ', 11, 27);

function assertValues(hint: vscode.InlayHint, expectedLabel: string, expectedLine: number, expectedCharacter: number) {
assert.equal(hint.label, expectedLabel);
assert.equal(hint.position.line, expectedLine);
assert.equal(hint.position.character, expectedCharacter);

assertInlayHintEqual(hints[0], { Label: 'InlayHints ', Position: { Line: 6, Column: 12 }, Data: {}, TextEdits: [{ StartLine: 6, StartColumn: 8, EndLine: 6, EndColumn: 11, NewText: 'InlayHints' }] });
assertInlayHintEqual(hints[1], { Label: ' InlayHints', Position: { Line: 7, Column: 27 }, Data: {}, TextEdits: [{ StartLine: 7, StartColumn: 27, EndLine: 7, EndColumn: 27, NewText: ' InlayHints' }] });
assertInlayHintEqual(hints[2], { Label: 'string ', Position: { Line: 8, Column: 28 }, Data: {}, TextEdits: [{ StartLine: 8, StartColumn: 28, EndLine: 8, EndColumn: 28, NewText: 'string ' }] });
assertInlayHintEqual(hints[3], { Label: 'i: ', Position: { Line: 9, Column: 17 }, Data: {}, TextEdits: [{ StartLine: 9, StartColumn: 17, EndLine: 9, EndColumn: 17, NewText: 'i: ' }] });
assertInlayHintEqual(hints[4], { Label: 'param1: ', Position: { Line: 10, Column: 15 }, Data: {}, TextEdits: [{ StartLine: 10, StartColumn: 15, EndLine: 10, EndColumn: 15, NewText: 'param1: ' }] });
assertInlayHintEqual(hints[5], { Label: 'param1: ', Position: { Line: 11, Column: 27 }, Data: {}, TextEdits: [{ StartLine: 11, StartColumn: 27, EndLine: 11, EndColumn: 27, NewText: 'param1: ' }] });

function assertInlayHintEqual(actual: vscode.InlayHint, expected: InlayHint) {
assert.equal(actual.label, expected.Label);
assert.equal(actual.position.line, expected.Position.Line);
assert.equal(actual.position.character, expected.Position.Column);

if (!actual.textEdits) {
assert.isUndefined(expected.TextEdits);
return;
}

assert.equal(actual.textEdits.length, expected.TextEdits.length);
for (let i = 0; i < actual.textEdits.length; i++) {
const actualTextEdit = actual.textEdits[i];
const expectedTextEdit = expected.TextEdits[i];

assertTextEditEqual(actualTextEdit, expectedTextEdit);
}
}

function assertTextEditEqual(actual: vscode.TextEdit, expected: LinePositionSpanTextChange) {
assert.equal(actual.range.start.line, expected.StartLine);
assert.equal(actual.range.start.character, expected.StartColumn);
assert.equal(actual.range.end.line, expected.EndLine);
assert.equal(actual.range.end.character, expected.EndColumn);
assert.equal(actual.newText, expected.NewText);
}
});
});