Skip to content
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

fix(language-service): return all typecheck files via getExternalFiles #40162

Closed
wants to merge 1 commit into from

Conversation

kyliau
Copy link
Contributor

@kyliau kyliau commented Dec 16, 2020

We need a means to preserve typecheck files when a project is reloaded,
otherwise the Ivy compiler will throw an error when it fails to find them in the program.
(The compiler is told by the IncrementalDriver that the tcfs exist.)
This commit implements getExternalFiles() called by the language
server to achieve this goal.

For more info see angular/vscode-ng-language-service#1030

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.io application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

@google-cla google-cla bot added the cla: yes label Dec 16, 2020
@kyliau kyliau added area: language-service Issues related to Angular's VS Code language service and removed cla: yes labels Dec 16, 2020
@ngbot ngbot bot modified the milestone: Backlog Dec 16, 2020
@google-cla google-cla bot added the cla: yes label Dec 16, 2020
@kyliau kyliau added the target: patch This PR is targeted for the next patch release label Dec 16, 2020
@kyliau kyliau marked this pull request as ready for review December 16, 2020 22:30
export function getExternalFiles(project: ts.server.Project): string[] {
const typecheckFiles: string[] = [];
for (const scriptInfo of project.getScriptInfos()) {
if (scriptInfo.scriptKind === ts.ScriptKind.External) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially I tried to get tcfs via source files in the program, but it's just way too complex and not worth the effort. The isShim() method does not work, because according to Andrew, the source file tagged by the compiler is not the same as the source file contained in the latest program. The other method, templateTypeChecker. isTrackedTypeCheckFile() involves instantiating the Ivy compiler and the ttc, so it's also quite involved.
We have three different methods to detect typecheck files now, so we should probably do a cleanup in the future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know if we'll have issues with this check if other plugins also register external files?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in the way this package (@angular/language-service) is used, because we control the server, and we know for sure the Angular language service is the only plugin installed.

'', // fileContent
// script info added by plugins should be marked as external, see
// https://github.com/microsoft/TypeScript/blob/b217f22e798c781f55d17da72ed099a9dee5c650/src/compiler/program.ts#L1897-L1899
ts.ScriptKind.External, // scriptKind
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I wonder if this has implications for "find references". Have you tried building the plugin with this change and running it in the extension host?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I did, and I can confirm that "find references" still works. From TS language service point of view, the script info kind doesn't really matter, whether they are TS or External, they all end up in the ts.Program (see code in the link above), so I doubt it'll affect "find references".

export function getExternalFiles(project: ts.server.Project): string[] {
const typecheckFiles: string[] = [];
for (const scriptInfo of project.getScriptInfos()) {
if (scriptInfo.scriptKind === ts.ScriptKind.External) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know if we'll have issues with this check if other plugins also register external files?

// Now that global analysis is run, we should have all the typecheck files
externalFiles = getExternalFiles(project);
expect(externalFiles.length).toBe(1);
expect(externalFiles[0].endsWith('app.component.ngtypecheck.ts')).toBeTrue();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a more e2e way that we can test this? Like triggering a reload on the project, either with a direct call to updateGraph or doing some other action that would trigger it organically and then asserting that our stuff still works?

Maybe a test like that is dependent on this PR being submitted first (since the e2e tests in the client depend on the published version of the plugin).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some integration tests for the VE-based language service in this repo. I think a test to make sure that the typeck files are kept after a project reload are a good idea, but should be done in angular/angular if we're going to do them.

Copy link
Contributor

@atscott atscott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

// Now that global analysis is run, we should have all the typecheck files
externalFiles = getExternalFiles(project);
expect(externalFiles.length).toBe(1);
expect(externalFiles[0].endsWith('app.component.ngtypecheck.ts')).toBeTrue();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some integration tests for the VE-based language service in this repo. I think a test to make sure that the typeck files are kept after a project reload are a good idea, but should be done in angular/angular if we're going to do them.

kyliau added a commit to kyliau/vscode-ng-language-service that referenced this pull request Dec 17, 2020
This is a follow-up to angular/angular#40162.

In View Engine, `getExternalFiles()` returns a list of external templates
(HTML files), but we should not have marked them as `ScriptKind.External`.

As noted in https://github.com/microsoft/TypeScript/blob/b217f22e798c781f55d17da72ed099a9dee5c650/src/compiler/program.ts#L1897-L1899
`ScriptKind.External` should be used for external TypeScript files added
by plugins.

External templates should be marked as `ScriptKind.Unknown` instead.
kyliau added a commit to kyliau/vscode-ng-language-service that referenced this pull request Dec 17, 2020
This is a follow-up to angular/angular#40162.

In View Engine, `getExternalFiles()` returns a list of external templates
(HTML files), but we should not have marked them as `ScriptKind.External`.

As noted in https://github.com/microsoft/TypeScript/blob/b217f22e798c781f55d17da72ed099a9dee5c650/src/compiler/program.ts#L1897-L1899
`ScriptKind.External` should be used for external TypeScript files added
by plugins.

External templates should be marked as `ScriptKind.Unknown` instead.
kyliau added a commit to kyliau/vscode-ng-language-service that referenced this pull request Dec 17, 2020
This is a follow-up to angular/angular#40162.

In View Engine, `getExternalFiles()` returns a list of external templates
(HTML files), but we should not have marked them as `ScriptKind.External`.

As noted in https://github.com/microsoft/TypeScript/blob/b217f22e798c781f55d17da72ed099a9dee5c650/src/compiler/program.ts#L1897-L1899
`ScriptKind.External` should be used for external TypeScript files added
by plugins.

External templates should be marked as `ScriptKind.Unknown` instead.
kyliau added a commit to angular/vscode-ng-language-service that referenced this pull request Dec 17, 2020
This is a follow-up to angular/angular#40162.

In View Engine, `getExternalFiles()` returns a list of external templates
(HTML files), but we should not have marked them as `ScriptKind.External`.

As noted in https://github.com/microsoft/TypeScript/blob/b217f22e798c781f55d17da72ed099a9dee5c650/src/compiler/program.ts#L1897-L1899
`ScriptKind.External` should be used for external TypeScript files added
by plugins.

External templates should be marked as `ScriptKind.Unknown` instead.
We need a means to preserve typecheck files when a project is reloaded,
otherwise the Ivy compiler will throw an error when it's unable to find
them. This commit implements `getExternalFiles()` called by the langauge
server to achieve this goal.

For more info see angular/vscode-ng-language-service#1030
@kyliau kyliau added target: minor This PR is targeted for the next minor release and removed target: patch This PR is targeted for the next patch release labels Jan 6, 2021
@kyliau
Copy link
Contributor Author

kyliau commented Jan 6, 2021

I'll merge this for now. Created https://github.com/orgs/angular/projects/1#card-52319541 to keep track of the integration test for project reload.

@kyliau kyliau added the action: merge The PR is ready for merge by the caretaker label Jan 6, 2021
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Feb 6, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: language-service Issues related to Angular's VS Code language service cla: yes target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants