Skip to content

Commit 546870c

Browse files
kyliauKeen Yee Liau
authored andcommitted
feat: add --experimental-ivy flag for Ivy language service
This commit adds a hidden flag `--experimental-ivy` to load the Ivy version of `@angular/language-service`. This flag is hidden for now because it is only used for development. The second entry point is resolved from `@angular/language-service/ivy.umd` but in the next update it'll be `@angular/language-service/ivy` due to the renaming done in angular/angular#38086
1 parent 05aa50b commit 546870c

File tree

5 files changed

+38
-12
lines changed

5 files changed

+38
-12
lines changed

server/src/cmdline_utils.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ function hasArgument(argv: string[], argName: string): boolean {
2828

2929
interface CommandLineOptions {
3030
help: boolean;
31+
/**
32+
* If true, use the Ivy version of Angular LS. For now this is only used for
33+
* development.
34+
*/
35+
ivy: boolean;
3136
logFile?: string;
3237
logVerbosity?: string;
3338
ngProbeLocations: string[];
@@ -37,6 +42,7 @@ interface CommandLineOptions {
3742
export function parseCommandLine(argv: string[]): CommandLineOptions {
3843
return {
3944
help: hasArgument(argv, '--help'),
45+
ivy: hasArgument(argv, '--experimental-ivy'),
4046
logFile: findArgument(argv, '--logFile'),
4147
logVerbosity: findArgument(argv, '--logVerbosity'),
4248
ngProbeLocations: parseStringArray(argv, '--ngProbeLocations'),
@@ -45,6 +51,7 @@ export function parseCommandLine(argv: string[]): CommandLineOptions {
4551
}
4652

4753
export function generateHelpMessage(argv: string[]) {
54+
// Do not expose --experimental-ivy flag since it's only used for development.
4855
return `Angular Language Service that implements the Language Server Protocol (LSP).
4956
5057
Usage: ${argv[0]} ${argv[1]} [options]

server/src/server.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const logger = createLogger({
2727
});
2828

2929
const ts = resolveTsServer(options.tsProbeLocations);
30-
const ng = resolveNgLangSvc(options.ngProbeLocations);
30+
const ng = resolveNgLangSvc(options.ngProbeLocations, options.ivy);
3131

3232
// ServerHost provides native OS functionality
3333
const host = new ServerHost();
@@ -36,13 +36,14 @@ const host = new ServerHost();
3636
const session = new Session({
3737
host,
3838
logger,
39+
ngPlugin: ng.name,
3940
ngProbeLocation: ng.resolvedPath,
4041
});
4142

4243
// Log initialization info
4344
session.info(`Angular language server process ID: ${process.pid}`);
44-
session.info(`Using typescript v${ts.version} from ${ts.resolvedPath}`);
45-
session.info(`Using @angular/language-service v${ng.version} from ${ng.resolvedPath}`);
45+
session.info(`Using ${ts.name} v${ts.version} from ${ts.resolvedPath}`);
46+
session.info(`Using ${ng.name} v${ng.version} from ${ng.resolvedPath}`);
4647
session.info(`Log file: ${logger.getLogFileName()}`);
4748
if (process.env.NG_DEBUG === 'true') {
4849
session.info('Angular Language Service is running under DEBUG mode');

server/src/session.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {filePathToUri, lspPositionToTsPosition, lspRangeToTsPositions, tsTextSpa
1919
export interface SessionOptions {
2020
host: ServerHost;
2121
logger: Logger;
22+
ngPlugin: string;
2223
ngProbeLocation: string;
2324
}
2425

@@ -62,7 +63,7 @@ export class Session {
6263
// See https://github.com/angular/vscode-ng-language-service/issues/693
6364
suppressDiagnosticEvents: true,
6465
eventHandler: (e) => this.handleProjectServiceEvent(e),
65-
globalPlugins: ['@angular/language-service'],
66+
globalPlugins: [options.ngPlugin],
6667
pluginProbeLocations: [options.ngProbeLocation],
6768
allowLocalPluginLoads: false, // do not load plugins from tsconfig.json
6869
});
@@ -79,7 +80,7 @@ export class Session {
7980
});
8081

8182
projSvc.configurePlugin({
82-
pluginName: '@angular/language-service',
83+
pluginName: options.ngPlugin,
8384
configuration: {
8485
angularOnly: true,
8586
},

server/src/tests/version_provider_spec.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,20 @@ describe('Node Module Resolver', () => {
1818
});
1919

2020
it('should be able to resolve Angular language service', () => {
21-
const result = resolveNgLangSvc(probeLocations);
21+
const result = resolveNgLangSvc(probeLocations, false /* ivy */);
2222
expect(result).toBeDefined();
23+
// TODO: This will fail in the next update of @angular/language-service
24+
// because language-service.umd.js is renamed to language-service.js
2325
expect(result.resolvedPath).toMatch(/language-service.umd.js$/);
2426
});
27+
28+
it('should be able to resolve Ivy version of Angular language service', () => {
29+
const result = resolveNgLangSvc(probeLocations, true /* ivy */);
30+
expect(result).toBeDefined();
31+
// TODO: This will fail in the next update of @angular/language-service
32+
// because ivy.umd.js is renamed to ivy.js
33+
expect(result.resolvedPath).toMatch(/ivy.umd.js$/);
34+
});
2535
});
2636

2737
describe('Version', () => {

server/src/version_provider.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const MIN_NG_VERSION = '10.0';
1313
* Represents a valid node module that has been successfully resolved.
1414
*/
1515
interface NodeModule {
16+
name: string;
1617
resolvedPath: string;
1718
version: Version;
1819
}
@@ -29,6 +30,7 @@ function resolve(packageName: string, location: string, rootPackage?: string): N
2930
paths: [location],
3031
});
3132
return {
33+
name: packageName,
3234
resolvedPath,
3335
version: new Version(packageJson.version),
3436
};
@@ -42,12 +44,13 @@ function resolve(packageName: string, location: string, rootPackage?: string): N
4244
* @param packageName name of package to be resolved
4345
* @param minVersionStr minimum version
4446
* @param probeLocations locations to initiate node module resolution
45-
* @param rootPackage location of package.json, if different from `packageName`
47+
* @param rootPackage location of package.json. For example, the root package of
48+
* `typescript/lib/tsserverlibrary` is `typescript`.
4649
*/
4750
function resolveWithMinVersion(
4851
packageName: string, minVersionStr: string, probeLocations: string[],
49-
rootPackage?: string): NodeModule {
50-
if (rootPackage && !packageName.startsWith(rootPackage)) {
52+
rootPackage: string): NodeModule {
53+
if (!packageName.startsWith(rootPackage)) {
5154
throw new Error(`${packageName} must be in the root package`);
5255
}
5356
const minVersion = new Version(minVersionStr);
@@ -73,11 +76,15 @@ export function resolveTsServer(probeLocations: string[]): NodeModule {
7376

7477
/**
7578
* Resolve `@angular/language-service` from the given locations.
76-
* @param probeLocations
79+
* @param probeLocations locations from which resolution is attempted
80+
* @param ivy true if Ivy language service is requested
7781
*/
78-
export function resolveNgLangSvc(probeLocations: string[]): NodeModule {
82+
export function resolveNgLangSvc(probeLocations: string[], ivy: boolean): NodeModule {
7983
const nglangsvc = '@angular/language-service';
80-
return resolveWithMinVersion(nglangsvc, MIN_NG_VERSION, probeLocations);
84+
// TODO: In the next update of @angular/language-service, rename this to
85+
// bundles/ivy because the file has been renamed
86+
const packageName = ivy ? `${nglangsvc}/bundles/ivy.umd` : nglangsvc;
87+
return resolveWithMinVersion(packageName, MIN_NG_VERSION, probeLocations, nglangsvc);
8188
}
8289

8390
/**

0 commit comments

Comments
 (0)