Skip to content

Commit e07b57a

Browse files
committed
fix: vscode url handling, loading imported models
1 parent 178a08b commit e07b57a

2 files changed

Lines changed: 83 additions & 6 deletions

File tree

packages/ide/vscode/src/extension/zenstack-auth-provider.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface JWTClaims {
1111
export const AUTH_PROVIDER_ID = 'ZenStack';
1212
export const AUTH_URL = 'https://accounts.zenstack.dev';
1313
export const API_URL = 'https://api.zenstack.dev';
14+
const EXTENSION_ID = 'zenstack.zenstack-v3';
1415

1516
export class ZenStackAuthenticationProvider implements vscode.AuthenticationProvider, vscode.Disposable {
1617
private _onDidChangeSessions =
@@ -111,19 +112,21 @@ export class ZenStackAuthenticationProvider implements vscode.AuthenticationProv
111112
reject(new Error('User Cancelled'));
112113
});
113114

114-
const appName =
115-
vscode.env.appName === 'Visual Studio Code' ? 'vscode' : vscode.env.appName.toLowerCase();
116-
const redirectUrl = `${API_URL}/oauth/oauth_callback?extId=zenstack.zenstack-v3&vscodeapp=${appName}`;
115+
const appName = vscode.env.uriScheme;
116+
const redirectUrl = `${API_URL}/oauth/oauth_callback?vscodeapp=${appName}&extId=${EXTENSION_ID}`;
117117
const signInUrl = vscode.Uri.parse(new URL('/sign-in', AUTH_URL).toString()).with({
118-
query: `redirect_url=${redirectUrl}`,
118+
query: `redirect_url=${encodeURIComponent(redirectUrl)}`,
119119
});
120120

121-
console.log('ZenStack sign-in URL:', signInUrl.toString());
121+
const finalUrl = signInUrl.toString(true);
122+
console.log('ZenStack sign-in URL:', finalUrl);
123+
122124
// Store the state and resolve function for later use
123125
this.pendingAuth = { resolve, reject, scopes };
124126

125127
// Open the ZenStack sign-in page in the user's default browser
126-
vscode.env.openExternal(signInUrl).then(
128+
// @ts-ignore - vscode issue: https://github.com/microsoft/vscode/issues/85930
129+
vscode.env.openExternal(finalUrl).then(
127130
() => {
128131
console.log('Opened ZenStack sign-in page in browser');
129132
progress.report({ message: 'Waiting for return from browser...' });

packages/ide/vscode/src/language-server/main.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { createZModelLanguageServices } from '@zenstackhq/language';
2+
import type { Model } from '@zenstackhq/language/ast';
3+
import { getDocument, resolveImport } from '@zenstackhq/language/utils';
4+
import { URI, type LangiumDocument, type LangiumDocuments } from 'langium';
25
import { startLanguageServer } from 'langium/lsp';
36
import { NodeFileSystem } from 'langium/node';
47
import { createConnection, ProposedFeatures } from 'vscode-languageserver/node.js';
@@ -15,5 +18,76 @@ const { shared } = createZModelLanguageServices(
1518
true,
1619
);
1720

21+
// Add custom LSP request handlers
22+
connection.onRequest('zenstack/getAllImportedZModelURIs', async (params: { textDocument: { uri: string } }) => {
23+
try {
24+
const uri = URI.parse(params.textDocument.uri);
25+
const document = await shared.workspace.LangiumDocuments.getOrCreateDocument(uri);
26+
27+
// Ensure the document is parsed and built
28+
if (!document.parseResult) {
29+
await shared.workspace.DocumentBuilder.build([document]);
30+
}
31+
32+
const langiumDocuments = shared.workspace.LangiumDocuments;
33+
34+
// load all imports
35+
const importedURIs = eagerLoadAllImports(document, langiumDocuments);
36+
37+
const importedDocuments = await Promise.all(
38+
importedURIs.map((uri) => langiumDocuments.getOrCreateDocument(uri)),
39+
);
40+
41+
// build the document together with standard library, plugin modules, and imported documents
42+
await shared.workspace.DocumentBuilder.build([document, ...importedDocuments], {
43+
validation: true,
44+
});
45+
46+
let hasSyntaxErrors = false;
47+
for (const docUri of [uri, ...importedURIs]) {
48+
const doc = await langiumDocuments.getOrCreateDocument(docUri);
49+
if (
50+
doc.parseResult.lexerErrors.length > 0 ||
51+
doc.parseResult.parserErrors.length > 0 ||
52+
doc.diagnostics?.some((e) => e.severity === 1)
53+
) {
54+
hasSyntaxErrors = true;
55+
break;
56+
}
57+
}
58+
59+
return {
60+
hasSyntaxErrors,
61+
importedURIs,
62+
};
63+
} catch (error) {
64+
console.error('Error getting imported ZModel file:', error);
65+
return {
66+
hasSyntaxErrors: true,
67+
importedURIs: [],
68+
};
69+
}
70+
});
71+
72+
function eagerLoadAllImports(document: LangiumDocument, documents: LangiumDocuments, uris: Set<string> = new Set()) {
73+
const uriString = document.uri.toString();
74+
if (!uris.has(uriString)) {
75+
uris.add(uriString);
76+
const model = document.parseResult.value as Model;
77+
78+
for (const imp of model.imports) {
79+
const importedModel = resolveImport(documents, imp);
80+
if (importedModel) {
81+
const importedDoc = getDocument(importedModel);
82+
eagerLoadAllImports(importedDoc, documents, uris);
83+
}
84+
}
85+
}
86+
87+
return Array.from(uris)
88+
.filter((x) => uriString != x)
89+
.map((e) => URI.parse(e));
90+
}
91+
1892
// Start the language server with the shared services
1993
startLanguageServer(shared);

0 commit comments

Comments
 (0)