* Fixes #886: Working extension inexplicably stopped sending document symbols

* Fixes #897: Header field name in jsonrpc Message has to be case-insensitive
This commit is contained in:
Dirk Bäumer 2022-12-07 09:52:07 +01:00 коммит произвёл GitHub
Родитель f02ec883a6
Коммит 55eb8e349c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 51 добавлений и 17 удалений

Просмотреть файл

@ -156,6 +156,7 @@ suite('Client integration', () => {
documentLinkProvider: {
resolveProvider: true
},
documentSymbolProvider: true,
colorProvider: true,
declarationProvider: true,
foldingRangeProvider: true,
@ -587,6 +588,29 @@ suite('Client integration', () => {
assert.strictEqual(middlewareCalled, 2);
});
test('Document Symbol', async () => {
const provider = client.getFeature(lsclient.DocumentSymbolRequest.method).getProvider(document);
isDefined(provider);
const result = await provider.provideDocumentSymbols(document, tokenSource.token);
const item = result ? result[0] : undefined;
isDefined(item);
const documentSymbol: vscode.DocumentSymbol = item as vscode.DocumentSymbol;
isInstanceOf(documentSymbol, vscode.DocumentSymbol);
assert.equal(documentSymbol.name, 'name');
rangeEqual(documentSymbol.range, 1, 1, 3, 1);
rangeEqual(documentSymbol.selectionRange, 2, 1, 2, 3);
let middlewareCalled: boolean = false;
middleware.provideDocumentSymbols = (d, t, n) => {
middlewareCalled = true;
return n(d, t);
};
await provider.provideDocumentSymbols(document, tokenSource.token);
middleware.provideDocumentSymbols = undefined;
assert.ok(middlewareCalled);
});
test('Document Color', async () => {
const provider = client.getFeature(lsclient.DocumentColorRequest.method).getProvider(document);
isDefined(provider);

Просмотреть файл

@ -11,7 +11,7 @@ import {
ColorInformation, Color, ColorPresentation, FoldingRange, SelectionRange, SymbolKind, ProtocolRequestType, WorkDoneProgress,
InlineValueText, InlineValueVariableLookup, InlineValueEvaluatableExpression, WorkDoneProgressCreateRequest, WillCreateFilesRequest,
WillRenameFilesRequest, WillDeleteFilesRequest, DidDeleteFilesNotification, DidRenameFilesNotification, DidCreateFilesNotification,
ProposedFeatures, Diagnostic, DiagnosticSeverity, TypeHierarchyItem, InlayHint, InlayHintLabelPart, InlayHintKind, DocumentDiagnosticReportKind
ProposedFeatures, Diagnostic, DiagnosticSeverity, TypeHierarchyItem, InlayHint, InlayHintLabelPart, InlayHintKind, DocumentDiagnosticReportKind, DocumentSymbol
} from 'vscode-languageserver/node';
import { URI } from 'vscode-uri';
@ -83,6 +83,7 @@ connection.onInitialize((params: InitializeParams): any => {
documentLinkProvider: {
resolveProvider: true
},
documentSymbolProvider: true,
colorProvider: true,
declarationProvider: true,
foldingRangeProvider: true,
@ -295,6 +296,12 @@ connection.onDocumentLinkResolve((link) => {
return link;
});
connection.onDocumentSymbol((_params) => {
return [
DocumentSymbol.create('name', undefined, SymbolKind.Method, Range.create(1, 1, 3, 1), Range.create(2, 1, 2, 3))
];
});
connection.onDocumentColor((_params) => {
return [
ColorInformation.create(Range.create(1, 1, 1, 2), Color.create(1, 2, 3, 4))

Просмотреть файл

@ -93,8 +93,9 @@ export class DocumentSymbolFeature extends TextDocumentLanguageFeature<boolean |
const provider: DocumentSymbolProvider = {
provideDocumentSymbols: (document, token) => {
const client = this._client;
const _provideDocumentSymbols: ProvideDocumentSymbolsSignature = (document, token) => {
return client.sendRequest(DocumentSymbolRequest.type, client.code2ProtocolConverter.asDocumentSymbolParams(document), token).then(async (data) => {
const _provideDocumentSymbols: ProvideDocumentSymbolsSignature = async (document, token) => {
try {
const data = await client.sendRequest(DocumentSymbolRequest.type, client.code2ProtocolConverter.asDocumentSymbolParams(document), token);
if (token.isCancellationRequested || data === undefined || data === null) {
return null;
}
@ -108,9 +109,9 @@ export class DocumentSymbolFeature extends TextDocumentLanguageFeature<boolean |
return await client.protocol2CodeConverter.asSymbolInformations(data as SymbolInformation[], token);
}
}
}, (error) => {
} catch (error) {
return client.handleFailedRequest(DocumentSymbolRequest.type, token, error, null);
});
}
};
const middleware = client.middleware;
return middleware.provideDocumentSymbols

Просмотреть файл

@ -38,10 +38,10 @@ suite('Browser IPC Reader / Writer', () => {
const encoder: TextEncoder = new TextEncoder();
buffer.append(encoder.encode('Content-Length: 43\r\n\r\n'));
buffer.append(encoder.encode('{"jsonrpc":"2.0","id":1,"method":"example"}'));
const headers = buffer.tryReadHeaders();
const headers = buffer.tryReadHeaders(true);
assertDefined(headers);
assert.strictEqual(headers.size, 1);
assert.strictEqual(headers.get('Content-Length'), '43');
assert.strictEqual(headers.get('content-length'), '43');
const decoder = new TextDecoder('utf-8');
const content = JSON.parse(decoder.decode(buffer.tryReadBody(43)));
assert.strictEqual(content.id, 1);
@ -75,7 +75,7 @@ suite('Browser IPC Reader / Writer', () => {
buffer.append(payload.slice(sent, sent + piece));
sent = sent + piece;
}
const headers = buffer.tryReadHeaders();
const headers = buffer.tryReadHeaders(false);
assertDefined(headers);
assert.strictEqual(headers.size, 1);
const length = parseInt(headers.get('Content-Length')!);

Просмотреть файл

@ -37,7 +37,7 @@ export abstract class AbstractMessageBuffer implements RAL.MessageBuffer {
this._totalLength += toAppend.byteLength;
}
public tryReadHeaders(): Map<string, string> | undefined {
public tryReadHeaders(lowerCaseKeys: boolean = false): Map<string, string> | undefined {
if (this._chunks.length === 0) {
return undefined;
}
@ -104,8 +104,7 @@ export abstract class AbstractMessageBuffer implements RAL.MessageBuffer {
}
const key = header.substr(0, index);
const value = header.substr(index + 1).trim();
result.set(key, value);
result.set(lowerCaseKeys ? key.toLowerCase() : key, value);
}
return result;
}

Просмотреть файл

@ -211,11 +211,11 @@ export class ReadableStreamMessageReader extends AbstractMessageReader {
this.buffer.append(data);
while (true) {
if (this.nextMessageLength === -1) {
const headers = this.buffer.tryReadHeaders();
const headers = this.buffer.tryReadHeaders(true);
if (!headers) {
return;
}
const contentLength = headers.get('Content-Length');
const contentLength = headers.get('content-length');
if (!contentLength) {
throw new Error('Header must provide a Content-Length property.');
}

Просмотреть файл

@ -19,10 +19,13 @@ interface _MessageBuffer {
/**
* Tries to read the headers from the buffer
*
* @param lowerCaseKeys Whether the keys should be stored lower case. Doing
* so is recommended since HTTP headers are case insensitive.
*
* @returns the header properties or undefined in not enough data can be read.
*/
tryReadHeaders(): Map<string, string> | undefined;
tryReadHeaders(lowerCaseKeys?: boolean): Map<string, string> | undefined;
/**
* Tries to read the body of the given length.

Просмотреть файл

@ -273,10 +273,10 @@ suite('Messages', () => {
const buffer = RIL().messageBuffer.create('utf-8');
buffer.append(Buffer.from('Content-Length: 43\r\n\r\n', 'ascii'));
buffer.append(Buffer.from('{"jsonrpc":"2.0","id":1,"method":"example"}', 'utf8'));
const headers = buffer.tryReadHeaders();
const headers = buffer.tryReadHeaders(true);
assertDefined(headers);
assert.strictEqual(headers.size, 1);
assert.strictEqual(headers.get('Content-Length'), '43');
assert.strictEqual(headers.get('content-length'), '43');
const content = JSON.parse((buffer.tryReadBody(43) as Buffer).toString('utf8'));
assert.strictEqual(content.id, 1);
assert.strictEqual(content.method, 'example');
@ -306,7 +306,7 @@ suite('Messages', () => {
buffer.append(payload.slice(sent, sent + piece));
sent = sent + piece;
}
const headers = buffer.tryReadHeaders();
const headers = buffer.tryReadHeaders(false);
assertDefined(headers);
assert.strictEqual(headers.size, 1);
const length = parseInt(headers.get('Content-Length')!);