Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion testbed/client/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export async function activate(context: ExtensionContext) {
documentSelector: [
{ language: 'bat' },
{ language: 'bat', notebook: '*' },
{ language: 'testbed' },
{ scheme: 'file', pattern: '**/.vscode/test.txt' }
],
synchronize: {
Expand Down Expand Up @@ -53,7 +54,8 @@ export async function activate(context: ExtensionContext) {
onFocus: true,
match: (selector, resource) => {
const fsPath = resource.fsPath;
return path.extname(fsPath) === '.bat';
const ext = path.extname(fsPath);
return ext === '.bat' || ext === '.testbed';
}
},
textSynchronization: {
Expand Down
11 changes: 11 additions & 0 deletions testbed/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@
"enabledApiProposals": [
],
"contributes": {
"languages": [
{
"id": "testbed",
"aliases": [
"Testbed"
],
"extensions": [
".testbed"
]
}
],
"commands": [
{
"command": "testbed.openFile",
Expand Down
22 changes: 21 additions & 1 deletion testbed/server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
SemanticTokensClientCapabilities, SemanticTokensLegend, SemanticTokensBuilder, SemanticTokensRegistrationType,
SemanticTokensRegistrationOptions, ProtocolNotificationType, ChangeAnnotation, WorkspaceChange, CompletionItemKind, DiagnosticSeverity,
DocumentDiagnosticReportKind, WorkspaceDiagnosticReport, NotebookDocuments, CompletionList, DidChangeConfigurationNotification,
NotificationType
NotificationType, ErrorCodes
} from 'vscode-languageserver/node';

import {
Expand Down Expand Up @@ -229,10 +229,18 @@ documents.onDidChangeContent((_event) => {
// void connection.sendDiagnostics({ uri: document.uri, diagnostics: validate(document) });
});

documents.onDidOpen((event) => {
connection.console.info(`Document opened: ${event.document.uri} ${event.document.version}`);
});

documents.onDidSave((event) => {
connection.console.info(`Document got saved: ${event.document.uri} ${event.document.version}`);
});

documents.onDidClose((event) => {
connection.console.info(`Document closed: ${event.document.uri}`);
});

connection.onDidChangeWatchedFiles((params) => {
connection.console.log('File change event received');
// documents.all().forEach(document => {
Expand Down Expand Up @@ -335,6 +343,18 @@ let versionCounter: number = 1;
connection.languages.diagnostics.on(async (param) => {
const uri = URI.parse(param.textDocument.uri);
const document = documents.get(param.textDocument.uri);
connection.console.info(`Diagnostic pull request for ${param.textDocument.uri} (open: ${document !== undefined})`);
// Reproduces microsoft/vscode-languageserver-node#1797 / #1771: after saving an
// "unsaved but named" buffer, the client closes the `untitled:` document and then
// still issues a `textDocument/diagnostic` request for that same, now closed,
// `untitled:` document. A real language server (e.g. tsserver) has no project for
// such a URI anymore and fails the request. We mimic that behavior here so the
// problematic flow surfaces as an error instead of being silently swallowed.
if (document === undefined && uri.scheme !== 'file') {
const message = `no project found for URI ${param.textDocument.uri}`;
connection.console.error(`error handling method 'textDocument/diagnostic': ${message}`);
throw new ResponseError(ErrorCodes.InvalidParams, message);
}
const content = document !== undefined
? document.getText()
: uri.scheme === 'file'
Expand Down
51 changes: 51 additions & 0 deletions testbed/workspace/repro-1797.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Repro: Diagnostics requested after saving an unsaved-but-named buffer

Reproduces [microsoft/vscode-languageserver-node#1797](https://github.com/microsoft/vscode-languageserver-node/issues/1797)
(a manifestation of [#1771](https://github.com/microsoft/vscode-languageserver-node/issues/1771)).

## What the testbed sets up

* The client registers a fake programming language `testbed` (files ending in
`.testbed`) in `../package.json` and adds it to both the `documentSelector` and
the `diagnosticPullOptions.match` filter in `../client/src/extension.ts`.
* The server (`../server/src/server.ts`) registers for the text document
notifications (`didOpen`, `didChange`, `didSave`, `didClose`) and the
`textDocument/diagnostic` pull request, logging each so the problematic
sequence is visible in the `Testbed` output channel.
* When a diagnostic pull arrives for a document that is **not open** and whose
scheme is **not** `file` (i.e. a closed `untitled:` buffer), the server fails
the request with `no project found for URI <uri>`, mirroring how a real
language server (e.g. tsserver) reacts.

## Steps to reproduce

1. Build the repo and the testbed:
```sh
npm install
npm run compile:testbed
```
2. Open this `testbed` folder in VS Code and run the `Launch Client` debug
configuration so the extension loads with the `workspace` folder.
3. In the Extension Development Host, open an **unsaved but named** buffer for the
fake language, e.g. from a terminal:
```sh
code-insiders ./newFile.testbed # or: code ./newFile.testbed
```
(or create a new file, set its language to `Testbed`, and keep it unsaved).
4. Type some content, for example:
```
const x = new Map();
x.
```
5. Save the file.

## Expected problematic behavior

On save, VS Code sends `didSave` for the `file:` URI, then `didChange` and
`didClose` for the original `untitled:` URI, and finally a
`textDocument/diagnostic` request for the now closed `untitled:` document. The
`Testbed` output channel shows:

```
error handling method 'textDocument/diagnostic': no project found for URI untitled:/.../newFile.testbed
```
2 changes: 2 additions & 0 deletions testbed/workspace/sample.testbed
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const x = new Map();
x.