GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — fix(language-server): recover project for external templates in solution-style workspaces by ShayanAbbas1 · Pull Request #69769 · angular/angular Conversation
|
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
AGENT: I have left an inline suggestion for refactoring to share code and avoid duplication.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| // not needed. | ||
| if (!project || project.projectKind !== ts.server.ProjectKind.Configured) { | ||
| const {configFileName} = this.projectService.openClientFile(scriptInfo.fileName); | ||
| let {configFileName} = this.projectService.openClientFile(scriptInfo.fileName); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
AGENT: Thanks for the fix! This is indeed necessary to recover the project association when it is lost after the template is already open.
However, the logic to recover the project by opening/closing the sibling TS file is duplicated from onDidOpenTextDocument. We should extract this into a shared helper method to keep the code clean and ensure consistent behavior (including the manual attachment fallback, which might also be beneficial for onDidOpenTextDocument).
I have verified this refactoring locally. Here is the suggested helper method and how it would simplify the code:
/** * Attempt to recover a configured project for an external template by opening * its sibling TS file. This is a best-effort recovery for solution-style workspaces. */ private tryRecoverProjectForExternalTemplate( scriptInfo: ts.server.ScriptInfo, ): ts.server.Project | null { if (!isExternalTemplate(scriptInfo.fileName)) { return null; } const maybeComponentTsPath = scriptInfo.fileName.replace(/\.html$/, '.ts'); if (!this.projectService.openFiles.has(this.projectService.toPath(maybeComponentTsPath))) { this.projectService.openClientFile(maybeComponentTsPath); this.projectService.closeClientFile(maybeComponentTsPath); } const componentProject = this.projectService .getScriptInfo(maybeComponentTsPath) ?.containingProjects.find(isConfiguredProject); if (componentProject) { scriptInfo.detachAllProjects(); scriptInfo.attachToProject(componentProject); return componentProject; } return null; }
You can then call this in getDefaultProjectForScriptInfo when configFileName is not found, and in onDidOpenTextDocument when result.configFileName is undefined.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Extracted, though as two methods rather than one: loadProjectForExternalTemplate(templatePath): boolean
for the open/close of the sibling TS file, and attachToComponentProject(scriptInfo) for the manual
attachment. The split is what let me share the logic without changing onDidOpenTextDocument's
existing behavior:
result = openClientFile(filePath, text, scriptKind)) is still there. That's theloadProjectForExternalTemplate returns whether it actually opened the component file, so thevoid helper the retry
Sorry, something went wrong.
There was an error while loading. Please reload this page.
d7d0fd9 to
2836d12
Compare
| * | ||
| * Returns whether the component file was opened, i.e. whether the config lookup for the template | ||
| * is worth retrying. | ||
| */ |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
AGENT: Consider checking !this.host.fileExists(maybeComponentTsPath) here to avoid attempting to open/close non-existent files (and walking directory trees looking for configs) when editing non-component HTML files like src/index.html:
| */ | |
| if ( | |
| this.projectService.openFiles.has(this.projectService.toPath(maybeComponentTsPath)) || | |
| !this.host.fileExists(maybeComponentTsPath) | |
| ) { |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Done
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…ion-style workspaces In a composite/solution-style workspace (e.g. an Nx monorepo, where an app's tsconfig.json only contains project references), TypeScript can never resolve a config file for an HTML file, since HTML files are not listed in any referenced project. angular/vscode-ng-language-service#2165 worked around this in onDidOpenTextDocument by briefly opening the sibling TS file so the right project loads when a template is opened first. However, getDefaultProjectForScriptInfo - the recovery path used by getLSAndScriptInfo and onDidChangeTextDocument when a script info has no configured project - did not receive the same workaround. When an open template loses its project association (e.g. its component file is closed and the project graph updates), every subsequent request on the template fails with "No config file" and returns null indefinitely, until the user manually reopens the component file. Apply the same sibling-TS best effort in getDefaultProjectForScriptInfo, and additionally attach the template's script info to the configured project of its component when the config lookup still comes back empty (openClientFile does not repeat the config lookup for already-open files). Also skip the sibling lookup when the .ts file does not exist, so non-component HTML files (e.g. src/index.html) do not trigger an open/close and config search that cannot succeed. Fixes angular#69768
2836d12 to
2b05055
Compare
There was an error while loading. Please reload this page.
|
This PR was merged into the repository. The changes were merged into the following branches: |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
This pull request has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
language-server: external templates permanently lose language service in solution-style (Nx) workspaces — getDefaultProjectForScriptInfo lacks the #2165 fallback
There was an error while loading. Please reload this page.