Skip to content

Commit fba3ffc

Browse files
author
Andrew Hall
authored
Merge branch 'main' into reference_integration_test
2 parents 03f884c + a098f04 commit fba3ffc

File tree

8 files changed

+116
-80
lines changed

8 files changed

+116
-80
lines changed

CHANGELOG.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@
55

66
# 2.77.x
77
* Bump xamlTools to 17.14.36106.43 (PR: [#8260](https://github.com/dotnet/vscode-csharp/pull/8260))
8-
* Bump Razor to 10.0.0-preview.25255.4 (PR: [#8249](https://github.com/dotnet/vscode-csharp/pull/8249))
8+
* Bump Razor to 10.0.0-preview.25256.6 (PR: [#8259](https://github.com/dotnet/vscode-csharp/pull/8259))
9+
* Improve document handling in VS Code and cohosting (#11825) (PR: [#11825](https://github.com/dotnet/razor/pull/11825))
10+
* Use new select and order method (#11826) (PR: [#11826](https://github.com/dotnet/razor/pull/11826))
11+
* Make it so validation happens after filtering and normalization (#11811) (PR: [#11811](https://github.com/dotnet/razor/pull/11811))
912
* Port remaining cohosting endpoints to VS Code (#11815) (PR: [#11815](https://github.com/dotnet/razor/pull/11815))
1013
* Fix cohost semantic tokens in VS Code (#11816) (PR: [#11816](https://github.com/dotnet/razor/pull/11816))
1114
* Fix some hardcoded values in cohosting (#11817) (PR: [#11817](https://github.com/dotnet/razor/pull/11817))
1215
* Add new shared SelectXXXAsArray helpers (#11796) (PR: [#11796](https://github.com/dotnet/razor/pull/11796))
13-
* Bump Roslyn to 5.0.0-1.25255.4 (PR: [#8249](https://github.com/dotnet/vscode-csharp/pull/8249))
14-
* Ensure hover markdown for supported platforms uses non-breaking spaces for indentation (#78405) (PR: [#78405](https://github.com/dotnet/roslyn/pull/78405))
15-
* Change O(n) + O(lg n) search in SolutionState.SortedProjectStates to just O(lg n) (#78427) (PR: [#78427](https://github.com/dotnet/roslyn/pull/78427))
16-
* Fix syntax tree creation when modifying source generated documents (#78343) (PR: [#78343](https://github.com/dotnet/roslyn/pull/78343))
1716

1817
# 2.76.x
1918
* Bump Roslyn to 5.0.0-1.25256.5 (PR: [#8254](https://github.com/dotnet/vscode-csharp/pull/8254))
2019
* Do not parse URIs during LSP serialization/deserialization(PR: [#76691](https://github.com/dotnet/roslyn/pull/76691))
2120
* Ensure hover markdown for supported platforms uses non-breaking spaces for indentation(PR: [#78405](https://github.com/dotnet/roslyn/pull/78405))
21+
* Change O(n) + O(lg n) search in SolutionState.SortedProjectStates to just O(lg n) (#78427) (PR: [#78427](https://github.com/dotnet/roslyn/pull/78427))
22+
* Fix syntax tree creation when modifying source generated documents (#78343) (PR: [#78343](https://github.com/dotnet/roslyn/pull/78343))
2223
* Bump Razor to 10.0.0-preview.25252.1 (PR: [#8239](https://github.com/dotnet/vscode-csharp/pull/8239))
2324
* If SupportDiagnostics is false then dynamic files don't report diagnostics... (PR: #11807)
2425
* Client settings tweaks, and implement VS Code configuration monitoring (PR: #11800)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"defaults": {
4343
"roslyn": "5.0.0-1.25256.5",
4444
"omniSharp": "1.39.12",
45-
"razor": "10.0.0-preview.25255.4",
45+
"razor": "10.0.0-preview.25256.6",
4646
"razorOmnisharp": "7.0.0-preview.23363.1",
4747
"xamlTools": "17.14.36106.43"
4848
},

src/lsptoolshost/razor/htmlDocument.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,23 @@ import { getUriPath } from '../../razor/src/uriPaths';
99
export class HtmlDocument {
1010
public readonly path: string;
1111
private content = '';
12+
private checksum = '';
1213

13-
public constructor(public readonly uri: vscode.Uri) {
14+
public constructor(public readonly uri: vscode.Uri, checksum: string) {
1415
this.path = getUriPath(uri);
16+
this.checksum = checksum;
1517
}
1618

1719
public getContent() {
1820
return this.content;
1921
}
2022

21-
public setContent(content: string) {
23+
public getChecksum() {
24+
return this.checksum;
25+
}
26+
27+
public setContent(checksum: string, content: string) {
28+
this.checksum = checksum;
2229
this.content = content;
2330
}
2431
}

src/lsptoolshost/razor/htmlDocumentManager.ts

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,22 @@ import { getUriPath } from '../../razor/src/uriPaths';
1010
import { virtualHtmlSuffix } from '../../razor/src/razorConventions';
1111
import { HtmlDocumentContentProvider } from './htmlDocumentContentProvider';
1212
import { HtmlDocument } from './htmlDocument';
13+
import { RoslynLanguageServer } from '../server/roslynLanguageServer';
14+
import { RequestType, TextDocumentIdentifier } from 'vscode-languageserver-protocol';
1315

1416
export class HtmlDocumentManager {
1517
private readonly htmlDocuments: { [hostDocumentPath: string]: HtmlDocument } = {};
1618
private readonly contentProvider: HtmlDocumentContentProvider;
1719

18-
constructor(private readonly platformInfo: PlatformInformation, private readonly logger: RazorLogger) {
20+
private readonly razorDocumentClosedRequest: RequestType<TextDocumentIdentifier, void, Error> = new RequestType(
21+
'razor/documentClosed'
22+
);
23+
24+
constructor(
25+
private readonly platformInfo: PlatformInformation,
26+
private readonly roslynLanguageServer: RoslynLanguageServer,
27+
private readonly logger: RazorLogger
28+
) {
1929
this.contentProvider = new HtmlDocumentContentProvider(this, this.logger);
2030
}
2131

@@ -37,7 +47,13 @@ export class HtmlDocumentManager {
3747

3848
await this.closeDocument(document.uri);
3949

40-
// TODO: Send a notification back to the server so it can cancel any pending sync requests and clear its cache.
50+
// We don't care about the response, but Razor cohosting can't currently do notifications with documents
51+
// so making it a request means the logs end up in the right place.
52+
await this.roslynLanguageServer.sendRequest(
53+
this.razorDocumentClosedRequest,
54+
TextDocumentIdentifier.create(getUriPath(document.uri)),
55+
new vscode.CancellationTokenSource().token
56+
);
4157
}
4258
});
4359

@@ -49,12 +65,22 @@ export class HtmlDocumentManager {
4965
return vscode.Disposable.from(didCloseRegistration, providerRegistration);
5066
}
5167

52-
public async updateDocumentText(uri: vscode.Uri, text: string) {
53-
const document = await this.getDocument(uri);
68+
public async updateDocumentText(uri: vscode.Uri, checksum: string, text: string) {
69+
// We don't pass the checksum in here, because we'd be comparing the new one against the old one.
70+
let document = await this.findDocument(uri);
71+
72+
if (!document) {
73+
this.logger.logTrace(
74+
`File '${uri}' didn't exist in the Razor document list, so adding it with checksum '${checksum}'.`
75+
);
76+
document = this.addDocument(uri, checksum);
77+
}
78+
79+
this.logger.logTrace(`New content for '${uri}', updating '${document.path}', checksum '${checksum}'.`);
5480

55-
this.logger.logTrace(`New content for '${uri}', updating '${document.path}'.`);
81+
await vscode.workspace.openTextDocument(document.uri);
5682

57-
document.setContent(text);
83+
document.setContent(checksum, text);
5884

5985
this.contentProvider.fireDidChange(document.uri);
6086
}
@@ -69,30 +95,36 @@ export class HtmlDocumentManager {
6995
}
7096
}
7197

72-
public async getDocument(uri: vscode.Uri): Promise<HtmlDocument> {
73-
let document = this.findDocument(uri);
98+
public async getDocument(uri: vscode.Uri, checksum?: string): Promise<HtmlDocument | undefined> {
99+
const document = this.findDocument(uri);
74100

75-
// This might happen in the case that a file is opened outside the workspace
76101
if (!document) {
102+
this.logger.logTrace(`File '${uri}' didn't exist in the Razor document list. Doing nothing.`);
103+
return undefined;
104+
}
105+
106+
if (checksum && document.getChecksum() !== checksum) {
77107
this.logger.logInfo(
78-
`File '${uri}' didn't exist in the Razor document list. This is likely because it's from outside the workspace.`
108+
`Found '${uri}' in the Razor document list, but the checksum '${document.getChecksum()}' doesn't match '${checksum}'.`
79109
);
80-
document = this.addDocument(uri);
110+
return undefined;
81111
}
82112

113+
// No checksum, just give them the latest document and hope they know what to do with it.
114+
83115
await vscode.workspace.openTextDocument(document.uri);
84116

85-
return document!;
117+
return document;
86118
}
87119

88-
private addDocument(uri: vscode.Uri): HtmlDocument {
120+
private addDocument(uri: vscode.Uri, checksum: string): HtmlDocument {
89121
let document = this.findDocument(uri);
90122
if (document) {
91123
this.logger.logInfo(`Skipping document creation for '${document.path}' because it already exists.`);
92124
return document;
93125
}
94126

95-
document = this.createDocument(uri);
127+
document = this.createDocument(uri, checksum);
96128
this.htmlDocuments[document.path] = document;
97129

98130
return document;
@@ -115,12 +147,12 @@ export class HtmlDocumentManager {
115147
);
116148
}
117149

118-
private createDocument(uri: vscode.Uri) {
150+
private createDocument(uri: vscode.Uri, checksum: string) {
119151
uri = uri.with({
120152
scheme: HtmlDocumentContentProvider.scheme,
121153
path: `${uri.path}${virtualHtmlSuffix}`,
122154
});
123-
const projectedDocument = new HtmlDocument(uri);
155+
const projectedDocument = new HtmlDocument(uri, checksum);
124156

125157
return projectedDocument;
126158
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
import { TextDocumentIdentifier } from 'vscode-languageserver-types';
6+
7+
export class HtmlForwardedRequest<Params> {
8+
constructor(
9+
public readonly textDocument: TextDocumentIdentifier,
10+
public readonly checksum: string,
11+
public readonly request: Params
12+
) {}
13+
}

src/lsptoolshost/razor/htmlUpdateParameters.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,9 @@
66
import { TextDocumentIdentifier } from 'vscode-languageserver-protocol';
77

88
export class HtmlUpdateParameters {
9-
constructor(public readonly textDocument: TextDocumentIdentifier, public readonly text: string) {}
9+
constructor(
10+
public readonly textDocument: TextDocumentIdentifier,
11+
public readonly checksum: string,
12+
public readonly text: string
13+
) {}
1014
}

src/lsptoolshost/razor/razorEndpoints.ts

Lines changed: 29 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ import { RazorMapTextChangesParams } from '../../razor/src/mapping/razorMapTextC
5050
import { RazorMapTextChangesResponse } from '../../razor/src/mapping/razorMapTextChangesResponse';
5151
import { FormattingHandler } from '../../razor/src/formatting/formattingHandler';
5252
import { ReportIssueCommand } from '../../razor/src/diagnostics/reportIssueCommand';
53+
import { HtmlDocument } from './htmlDocument';
54+
import { HtmlForwardedRequest } from './htmlForwardedRequest';
5355

5456
export function registerRazorEndpoints(
5557
context: vscode.ExtensionContext,
@@ -76,34 +78,25 @@ export function registerRazorEndpoints(
7678
// Local Functions
7779
//
7880
function registerCohostingEndpoints() {
79-
const documentManager = new HtmlDocumentManager(platformInfo, razorLogger);
81+
const documentManager = new HtmlDocumentManager(platformInfo, roslynLanguageServer, razorLogger);
8082
const reportIssueCommand = new ReportIssueCommand(vscode, undefined, documentManager, razorLogger);
8183
context.subscriptions.push(documentManager.register());
8284
context.subscriptions.push(reportIssueCommand.register());
8385

8486
registerMethodHandler<HtmlUpdateParameters, void>('razor/updateHtml', async (params) => {
8587
const uri = UriConverter.deserialize(params.textDocument.uri);
86-
await documentManager.updateDocumentText(uri, params.text);
88+
await documentManager.updateDocumentText(uri, params.checksum, params.text);
8789
});
8890

89-
registerRequestHandler(DocumentColorRequest.type, async (params) => {
90-
const uri = UriConverter.deserialize(params.textDocument.uri);
91-
const document = await documentManager.getDocument(uri);
92-
91+
registerCohostHandler(DocumentColorRequest.type, documentManager, async (document) => {
9392
return await DocumentColorHandler.doDocumentColorRequest(document.uri);
9493
});
9594

96-
registerRequestHandler(ColorPresentationRequest.type, async (params) => {
97-
const uri = UriConverter.deserialize(params.textDocument.uri);
98-
const document = await documentManager.getDocument(uri);
99-
95+
registerCohostHandler(ColorPresentationRequest.type, documentManager, async (document, params) => {
10096
return await ColorPresentationHandler.doColorPresentationRequest(document.uri, params);
10197
});
10298

103-
registerRequestHandler(FoldingRangeRequest.type, async (params) => {
104-
const uri = UriConverter.deserialize(params.textDocument.uri);
105-
const document = await documentManager.getDocument(uri);
106-
99+
registerCohostHandler(FoldingRangeRequest.type, documentManager, async (document) => {
107100
const results = await vscode.commands.executeCommand<vscode.FoldingRange[]>(
108101
'vscode.executeFoldingRangeProvider',
109102
document.uri
@@ -112,10 +105,7 @@ export function registerRazorEndpoints(
112105
return FoldingRangeHandler.convertFoldingRanges(results, razorLogger);
113106
});
114107

115-
registerRequestHandler(HoverRequest.type, async (params) => {
116-
const uri = UriConverter.deserialize(params.textDocument.uri);
117-
const document = await documentManager.getDocument(uri);
118-
108+
registerCohostHandler(HoverRequest.type, documentManager, async (document, params) => {
119109
const results = await vscode.commands.executeCommand<vscode.Hover[]>(
120110
'vscode.executeHoverProvider',
121111
document.uri,
@@ -126,10 +116,7 @@ export function registerRazorEndpoints(
126116
return rewriteHover(applicableHover);
127117
});
128118

129-
registerRequestHandler(DocumentHighlightRequest.type, async (params) => {
130-
const uri = UriConverter.deserialize(params.textDocument.uri);
131-
const document = await documentManager.getDocument(uri);
132-
119+
registerCohostHandler(DocumentHighlightRequest.type, documentManager, async (document, params) => {
133120
const results = await vscode.commands.executeCommand<vscode.DocumentHighlight[]>(
134121
'vscode.executeDocumentHighlights',
135122
document.uri,
@@ -139,21 +126,15 @@ export function registerRazorEndpoints(
139126
return rewriteHighlight(results);
140127
});
141128

142-
registerRequestHandler(CompletionRequest.type, async (params) => {
143-
const uri = UriConverter.deserialize(params.textDocument.uri);
144-
const document = await documentManager.getDocument(uri);
145-
129+
registerCohostHandler(CompletionRequest.type, documentManager, async (document, params) => {
146130
return CompletionHandler.provideVscodeCompletions(
147131
document.uri,
148132
params.position,
149133
params.context?.triggerCharacter
150134
);
151135
});
152136

153-
registerRequestHandler(ReferencesRequest.type, async (params) => {
154-
const uri = UriConverter.deserialize(params.textDocument.uri);
155-
const document = await documentManager.getDocument(uri);
156-
137+
registerCohostHandler(ReferencesRequest.type, documentManager, async (document, params) => {
157138
const results = await vscode.commands.executeCommand<vscode.Location[]>(
158139
'vscode.executeReferenceProvider',
159140
document.uri,
@@ -163,10 +144,7 @@ export function registerRazorEndpoints(
163144
return rewriteLocations(results);
164145
});
165146

166-
registerRequestHandler(ImplementationRequest.type, async (params) => {
167-
const uri = UriConverter.deserialize(params.textDocument.uri);
168-
const document = await documentManager.getDocument(uri);
169-
147+
registerCohostHandler(ImplementationRequest.type, documentManager, async (document, params) => {
170148
const results = await vscode.commands.executeCommand<vscode.Location[]>(
171149
'vscode.executeImplementationProvider',
172150
document.uri,
@@ -176,10 +154,7 @@ export function registerRazorEndpoints(
176154
return rewriteLocations(results);
177155
});
178156

179-
registerRequestHandler(DefinitionRequest.type, async (params) => {
180-
const uri = UriConverter.deserialize(params.textDocument.uri);
181-
const document = await documentManager.getDocument(uri);
182-
157+
registerCohostHandler(DefinitionRequest.type, documentManager, async (document, params) => {
183158
const results = await vscode.commands.executeCommand<vscode.Location[]>(
184159
'vscode.executeDefinitionProvider',
185160
document.uri,
@@ -189,10 +164,7 @@ export function registerRazorEndpoints(
189164
return rewriteLocations(results);
190165
});
191166

192-
registerRequestHandler(SignatureHelpRequest.type, async (params) => {
193-
const uri = UriConverter.deserialize(params.textDocument.uri);
194-
const document = await documentManager.getDocument(uri);
195-
167+
registerCohostHandler(SignatureHelpRequest.type, documentManager, async (document, params) => {
196168
const results = await vscode.commands.executeCommand<vscode.SignatureHelp>(
197169
'vscode.executeSignatureHelpProvider',
198170
document.uri,
@@ -206,21 +178,15 @@ export function registerRazorEndpoints(
206178
return rewriteSignatureHelp(results);
207179
});
208180

209-
registerRequestHandler(DocumentFormattingRequest.type, async (params) => {
210-
const uri = UriConverter.deserialize(params.textDocument.uri);
211-
const document = await documentManager.getDocument(uri);
212-
181+
registerCohostHandler(DocumentFormattingRequest.type, documentManager, async (document, params) => {
213182
const content = document.getContent();
214183
const options = <vscode.FormattingOptions>params.options;
215184

216185
const response = await FormattingHandler.getHtmlFormattingResult(document.uri, content, options);
217186
return response?.edits;
218187
});
219188

220-
registerRequestHandler(DocumentOnTypeFormattingRequest.type, async (params) => {
221-
const uri = UriConverter.deserialize(params.textDocument.uri);
222-
const document = await documentManager.getDocument(uri);
223-
189+
registerCohostHandler(DocumentOnTypeFormattingRequest.type, documentManager, async (document, params) => {
224190
const content = document.getContent();
225191
const options = <vscode.FormattingOptions>params.options;
226192

@@ -262,11 +228,21 @@ export function registerRazorEndpoints(
262228
}
263229

264230
// Helper method that registers a request handler, and logs errors to the Razor logger.
265-
function registerRequestHandler<Params, Result, Error>(
231+
function registerCohostHandler<Params, Result, Error>(
266232
type: RequestType<Params, Result, Error>,
267-
invocation: (params: Params) => Promise<Result>
233+
documentManager: HtmlDocumentManager,
234+
invocation: (document: HtmlDocument, request: Params) => Promise<Result>
268235
) {
269-
return registerMethodHandler<Params, Result>(type.method, invocation);
236+
return registerMethodHandler<HtmlForwardedRequest<Params>, Result | undefined>(type.method, async (params) => {
237+
const uri = UriConverter.deserialize(params.textDocument.uri);
238+
const document = await documentManager.getDocument(uri, params.checksum);
239+
240+
if (!document) {
241+
return undefined;
242+
}
243+
244+
return invocation(document, params.request);
245+
});
270246
}
271247

272248
function registerMethodHandler<Params, Result>(method: string, invocation: (params: Params) => Promise<Result>) {

0 commit comments

Comments
 (0)