Skip to content

refactor(client): Show warning message if a project uses a newer vers… #1942

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 19, 2023
Merged
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
36 changes: 29 additions & 7 deletions client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as lsp from 'vscode-languageclient/node';

import {OpenOutputChannel, ProjectLoadingFinish, ProjectLoadingStart, SuggestStrictMode, SuggestStrictModeParams} from '../../common/notifications';
import {GetComponentsWithTemplateFile, GetTcbRequest, GetTemplateLocationForComponent, IsInAngularProject} from '../../common/requests';
import {resolve} from '../../common/resolver';

import {isInsideComponentDecorator, isInsideInlineTemplateRegion, isInsideStringLiteral} from './embedded_support';

Expand Down Expand Up @@ -404,7 +405,7 @@ function getProbeLocations(bundled: string): string[] {
* Construct the arguments that's used to spawn the server process.
* @param ctx vscode extension context
*/
function constructArgs(ctx: vscode.ExtensionContext, isTrustedWorkspace: boolean): string[] {
function constructArgs(ctx: vscode.ExtensionContext): string[] {
const config = vscode.workspace.getConfiguration();
const args: string[] = ['--logToConsole'];

Expand Down Expand Up @@ -451,19 +452,20 @@ function getServerOptions(ctx: vscode.ExtensionContext, debug: boolean): lsp.Nod
NG_DEBUG: true,
};

// Because the configuration is typed as "boolean" in package.json, vscode
// will return false even when the value is not set. If value is false, then
// we need to check if all projects support Ivy language service.
const config = vscode.workspace.getConfiguration();

// Node module for the language server
const args = constructArgs(ctx, vscode.workspace.isTrusted);
const args = constructArgs(ctx);
const prodBundle = ctx.asAbsolutePath('server');
const devBundle = ctx.asAbsolutePath(path.join('bazel-bin', 'server', 'src', 'server.js'));
// VS Code Insider launches extensions in debug mode by default but users
// install prod bundle so we have to check whether dev bundle exists.
const latestServerModule = debug && fs.existsSync(devBundle) ? devBundle : prodBundle;

if (!extensionVersionCompatibleWithAllProjects(latestServerModule)) {
vscode.window.showWarningMessage(
`A project in the workspace is using a newer version of Angular than the language service extension. ` +
`This may cause the extension to show incorrect diagnostics.`);
}

// Argv options for Node.js
const prodExecArgv: string[] = [];
const devExecArgv: string[] = [
Expand All @@ -483,3 +485,23 @@ function getServerOptions(ctx: vscode.ExtensionContext, debug: boolean): lsp.Nod
},
};
}

function extensionVersionCompatibleWithAllProjects(serverModuleLocation: string): boolean {
const languageServiceVersion =
resolve('@angular/language-service', serverModuleLocation)?.version;
if (languageServiceVersion === undefined) {
return true;
}

const workspaceFolders = vscode.workspace.workspaceFolders || [];
for (const workspaceFolder of workspaceFolders) {
const angularCore = resolve('@angular/core', workspaceFolder.uri.fsPath);
if (angularCore === undefined) {
continue;
}
if (!languageServiceVersion.greaterThanOrEqual(angularCore.version, 'minor')) {
return false;
}
}
return true;
}
6 changes: 3 additions & 3 deletions common/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,17 @@ export class Version {
this.patch = patch;
}

greaterThanOrEqual(other: Version): boolean {
greaterThanOrEqual(other: Version, compare: 'patch'|'minor'|'major' = 'patch'): boolean {
if (this.major < other.major) {
return false;
}
if (this.major > other.major) {
if (this.major > other.major || (this.major === other.major && compare === 'major')) {
return true;
}
if (this.minor < other.minor) {
return false;
}
if (this.minor > other.minor) {
if (this.minor > other.minor || (this.minor === other.minor && compare === 'minor')) {
return true;
}
return this.patch >= other.patch;
Expand Down