Skip to content

Commit 759b1d4

Browse files
committed
Wire R language providers into SAS LSP server
Signed-off-by: Elijah Cúchulainn Reid <[email protected]>
1 parent 62e89e8 commit 759b1d4

File tree

3 files changed

+114
-3
lines changed

3 files changed

+114
-3
lines changed

server/src/browser/server.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
} from "vscode-languageserver/browser";
99

1010
import { PyrightLanguageProviderBrowser } from "../python/browser/PyrightLanguageProviderBrowser";
11+
import { RLanguageProviderBrowser } from "../r/browser/RLanguageProviderBrowser";
1112
import { runServer } from "../server";
1213

1314
/* browser specific setup code */
@@ -16,4 +17,8 @@ const messageWriter = new BrowserMessageWriter(self);
1617

1718
const connection: Connection = createConnection(messageReader, messageWriter);
1819

19-
runServer(connection, new PyrightLanguageProviderBrowser(connection, 1));
20+
runServer(
21+
connection,
22+
new PyrightLanguageProviderBrowser(connection, 1),
23+
new RLanguageProviderBrowser(connection),
24+
);

server/src/node/server.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@ import { Connection } from "vscode-languageserver";
44
import { ProposedFeatures, createConnection } from "vscode-languageserver/node";
55

66
import { PyrightLanguageProviderNode } from "../python/node/PyrightLanguageProviderNode";
7+
import { RLanguageProviderNode } from "../r/node/RLanguageProviderNode";
78
import { runServer } from "../server";
89

910
const connection: Connection = createConnection(ProposedFeatures.all);
1011

11-
runServer(connection, new PyrightLanguageProviderNode(connection, 1));
12+
runServer(
13+
connection,
14+
new PyrightLanguageProviderNode(connection, 1),
15+
new RLanguageProviderNode(connection),
16+
);

server/src/server.ts

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { CollectionResult } from "pyright-internal-node/dist/packages/pyright-in
3838
import { ParseFileResults } from "pyright-internal-node/dist/packages/pyright-internal/src/parser/parser";
3939

4040
import { PyrightLanguageProvider } from "./python/PyrightLanguageProvider";
41+
import { RLanguageProvider } from "./r/RLanguageProvider";
4142
import { CodeZoneManager } from "./sas/CodeZoneManager";
4243
import { LanguageServiceProvider, legend } from "./sas/LanguageServiceProvider";
4344
import type { LibCompleteItem } from "./sas/SyntaxDataProvider";
@@ -52,13 +53,15 @@ interface DocumentInfo {
5253
export const runServer = (
5354
connection: Connection,
5455
_pyrightLanguageProvider: PyrightLanguageProvider,
56+
_rLanguageProvider: RLanguageProvider,
5557
) => {
5658
const documentPool: Record<string, DocumentInfo> = {};
5759

5860
let supportSASGetLibList = false;
5961
let registeredAdvancedCapabilities = false;
6062

6163
_pyrightLanguageProvider.setSasLspProvider(getLanguageService);
64+
_rLanguageProvider.setSasLspProvider(getLanguageService);
6265

6366
connection.onInitialize((params) => {
6467
if (
@@ -117,7 +120,10 @@ export const runServer = (
117120
return result;
118121
});
119122

120-
connection.onInitialized(() => _pyrightLanguageProvider.onInitialized());
123+
connection.onInitialized(() => {
124+
_pyrightLanguageProvider.onInitialized();
125+
_rLanguageProvider.onInitialized();
126+
});
121127

122128
connection.onRequest(SemanticTokensRequest.type, (params) => {
123129
syncIfDocChange(params.textDocument.uri);
@@ -136,6 +142,9 @@ export const runServer = (
136142
async python(pyrightLanguageService) {
137143
return await pyrightLanguageService.onHover(params, token);
138144
},
145+
async r(rLanguageService) {
146+
return await rLanguageService.onHover(params, token);
147+
},
139148
});
140149
});
141150

@@ -216,6 +225,53 @@ export const runServer = (
216225
}
217226
return completionList;
218227
},
228+
async r(rLanguageService) {
229+
const completionList = await rLanguageService.onCompletion(
230+
params,
231+
token,
232+
);
233+
if (completionList) {
234+
for (const item of completionList.items) {
235+
if (!item.data) {
236+
item.data = {};
237+
}
238+
item.data._languageService = "r";
239+
item.data._uri = params.textDocument.uri;
240+
}
241+
242+
if (
243+
params.context?.triggerKind === CompletionTriggerKind.Invoked ||
244+
params.context?.triggerKind ===
245+
CompletionTriggerKind.TriggerForIncompleteCompletions
246+
) {
247+
const doc = documentPool[params.textDocument.uri].document;
248+
const line = doc.getText({
249+
start: {
250+
line: params.position.line,
251+
character: 0,
252+
},
253+
end: params.position,
254+
});
255+
if (!/\W/.test(line.trimStart())) {
256+
const item = {
257+
kind: CompletionItemKind.Keyword,
258+
data: {
259+
_languageService: "sas",
260+
_uri: params.textDocument.uri,
261+
},
262+
};
263+
if (
264+
completionList.items.findIndex(
265+
(item) => item.label === "endsubmit",
266+
) === -1
267+
) {
268+
completionList.items.push({ ...item, label: "endsubmit" });
269+
}
270+
}
271+
}
272+
}
273+
return completionList;
274+
},
219275
});
220276
});
221277

@@ -231,6 +287,11 @@ export const runServer = (
231287
completionItem,
232288
token,
233289
);
290+
} else if (lang === "r") {
291+
return await _rLanguageProvider.onCompletionResolve(
292+
completionItem,
293+
token,
294+
);
234295
}
235296
return completionItem;
236297
});
@@ -329,6 +390,14 @@ export const runServer = (
329390
// eslint-disable-next-line @typescript-eslint/no-explicit-any
330391
)) as any;
331392
},
393+
async r(rLanguageService) {
394+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
395+
return (await rLanguageService.onSignatureHelp(
396+
params,
397+
token,
398+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
399+
)) as any;
400+
},
332401
});
333402
});
334403

@@ -350,12 +419,14 @@ export const runServer = (
350419
);
351420
documentPool[doc.uri] = { document: doc, changed: false };
352421
await _pyrightLanguageProvider.onDidOpenTextDocument(params);
422+
await _rLanguageProvider.onDidOpenTextDocument(params);
353423
});
354424

355425
connection.onDidCloseTextDocument(async (params) => {
356426
const uri = params.textDocument.uri;
357427
delete documentPool[uri];
358428
await _pyrightLanguageProvider.onDidCloseTextDocument(params);
429+
await _rLanguageProvider.onDidCloseTextDocument(params);
359430
});
360431

361432
connection.onDidChangeTextDocument((params) => {
@@ -382,6 +453,9 @@ export const runServer = (
382453
async python(pyrightLanguageService) {
383454
return await pyrightLanguageService.onDefinition(params, token);
384455
},
456+
async r(rLanguageService) {
457+
return await rLanguageService.onDefinition(params, token);
458+
},
385459
});
386460
},
387461
);
@@ -562,6 +636,7 @@ export const runServer = (
562636

563637
connection.onShutdown(async (token) => {
564638
await _pyrightLanguageProvider.onShutdown(token);
639+
await _rLanguageProvider.onShutdown(token);
565640
});
566641

567642
// Listen on the connection
@@ -591,9 +666,11 @@ export const runServer = (
591666
python?: (
592667
pyrightLanguageService: PyrightLanguageProvider,
593668
) => Promise<Ret>;
669+
r?: (rLanguageService: RLanguageProvider) => Promise<Ret>;
594670
default?: (languageServices: {
595671
sasLanguageService: LanguageServiceProvider;
596672
pythonLanguageService?: PyrightLanguageProvider;
673+
rLanguageService?: RLanguageProvider;
597674
}) => Promise<Ret>;
598675
},
599676
) => {
@@ -627,6 +704,24 @@ export const runServer = (
627704
return await callbacks.default({
628705
sasLanguageService: languageService,
629706
pythonLanguageService: _pyrightLanguageProvider,
707+
rLanguageService: _rLanguageProvider,
708+
});
709+
} else {
710+
return undefined;
711+
}
712+
}
713+
if (
714+
symbol.name?.toUpperCase() === "PROC RLANG" &&
715+
codeZoneManager.getCurrentZone(pos.line, pos.character) ===
716+
CodeZoneManager.ZONE_TYPE.EMBEDDED_LANG
717+
) {
718+
if (callbacks.r) {
719+
return await callbacks.r(_rLanguageProvider);
720+
} else if (callbacks.default) {
721+
return await callbacks.default({
722+
sasLanguageService: languageService,
723+
pythonLanguageService: _pyrightLanguageProvider,
724+
rLanguageService: _rLanguageProvider,
630725
});
631726
} else {
632727
return undefined;
@@ -640,6 +735,7 @@ export const runServer = (
640735
return await callbacks.default({
641736
sasLanguageService: languageService,
642737
pythonLanguageService: _pyrightLanguageProvider,
738+
rLanguageService: _rLanguageProvider,
643739
});
644740
}
645741
{
@@ -660,11 +756,16 @@ export const runServer = (
660756

661757
const syncIfDocChange = (uri: string) => {
662758
const docInfo = documentPool[uri];
759+
if (!docInfo) {
760+
// Document not in pool yet - this can happen if hover is triggered before onDidOpenTextDocument
761+
return;
762+
}
663763
if (!docInfo.changed) {
664764
return;
665765
}
666766
docInfo.changed = false;
667767
_pyrightLanguageProvider.addContentChange(docInfo.document);
768+
_rLanguageProvider.addContentChange(docInfo.document);
668769
};
669770

670771
const syncAllChangedDoc = () => {

0 commit comments

Comments
 (0)