-
Notifications
You must be signed in to change notification settings - Fork 30.3k
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
[HTML] Support the tsserver resolving files relative to the html file #121517
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The one thing which I'd love some advice on is how I should invalidate the files which TypeScript sees. E.g. right now if I edit the exports for a module referenced in the script, the jsLanguageService
doesn't know the file content needs updating.
Is there a general file watcher I can hook into for the workspace - where I can then tell the language service to clear the cache.
// Both \ and / must be escaped in regular expressions | ||
return newPath.replace(new RegExp('\\' + sep, 'g'), '/'); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Key part 1: file://a/b/c.html
-> /a/b/c.html
so that TypeScript is always working with pure file paths
function getLanguageServiceHost(scriptKind: ts.ScriptKind) { | ||
const compilerOptions: ts.CompilerOptions = { allowNonTsExtensions: true, allowJs: true, lib: ['lib.es6.d.ts'], target: ts.ScriptTarget.Latest, moduleResolution: ts.ModuleResolutionKind.Classic, experimentalDecorators: false }; | ||
|
||
let currentTextDocument = TextDocument.create('init', 'javascript', 1, ''); | ||
let currentWorkspace: Workspace = undefined!; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Key part 2: Using the local workspace to act as the TS project root
This could maybe instead be based solely on the input .html file instead? It felt preferable to use the workspace, but I could understand opting for the folder the html lives in instead.
readFile: ts.sys.readFile, | ||
readDirectory: ts.sys.readDirectory, | ||
directoryExists: ts.sys.directoryExists, | ||
getDirectories: ts.sys.getDirectories, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Key part 3: Reuse the TypeScript fs functions to let this TSServer read from the fs
const filePath = deschemeURI(jsDocument.uri); | ||
|
||
const syntaxDiagnostics: ts.Diagnostic[] = languageService.getSyntacticDiagnostics(filePath); | ||
const semanticDiagnostics = languageService.getSemanticDiagnostics(filePath); | ||
return syntaxDiagnostics.concat(semanticDiagnostics).map((diag: ts.Diagnostic): Diagnostic => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes here are adding , workspace)
and then using filePath
whenever the LSP talks to the language service explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same pattern for the rest of the file
Hi. Unfortunately, the Microsoft team does not want to address this issue intentionally, so merging is unlikely. They ignore it for 4 years. Please make an extension to vscode. And thank you for working to solve this problem. :-) |
That's not a very helpful comment, the vscode team's project has a massive scope and the issues for this are both backlog'd and still open. This is generally a good indicator that they would accept a small and tested 3rd party PR for those items. Though, FWIW, I am also a Microsoft employee and I've definitely got backlog issues far far longer. |
Thanks for helping out, @orta ! Yes file watching is needed and access to the unsaved text documents. -> the html server needs to subscribe for open JS documents as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol ive always wanted this, tired of my inline js being plain text. Thanks for making this fix
OK, I've got this green and seems to work exactly how I expect overall. Right now, it uses mtime on app js/ts files to determine if it needs to be re-grabbed, which is potentially little resource wasteful but also can handle all of the different possible files which people use in JS (think packagers like webpack which allow for importing a .css files into a JS file) That said, I'd like to give it one more look to see what expanding using the watcher for html files looks like. So this is good enough if you want to try locally, but I'd like to at least give that one more run before being considered fully ready for review. |
Thanks @orta! We'd still need to look into unsaved files. |
I think it's safe to say that it's unlikely the tsserver api will be async in a reasonable timeframe (if ever) microsoft/TypeScript#29361 tracks it. I am kinda interested in how that works out for the official TS extension in Code, though the implementation differs because that is process separated and can probably have different constraints. So far, I think this leaves us with the following options:
|
I think making this turn itself off elegantly (and basically providing the same experience there is today) in the cases where we don't have sync access to a filesystem probably makes the most sense |
Is there a recommended system-level way to detect we're in a browser and then I can disable the TSServer? |
You could look at the schema of the workspace folder(s) and if it is not |
@orta Great PR! I really hope this one is being merged sooner or later. Until then: Have you released any extension based on this? I'd really like to have this instead of the internal one. |
b93b60b
to
10a4096
Compare
Wow, thank you so much already! |
@orta Is there anything, one could help with? |
Nah, I've just not had a chance to get back to the PR, you're welcome to rebase and get the tests green - that's all there is to do atm. I just need to find the time and inclination to wrap it up |
@orta Ah cool, thanks for the quick response. Let me see if I can manage it. This feature is very helpful for tooling that is focusing on "back to the roots" workflows/architectures (see Island Arch https://jasonformat.com/islands-architecture/) or web components and such; making the use of |
Yeah, I originally started this PR because I wanted to use this in my snowpack/vite apps |
10a4096
to
e4d3ca9
Compare
The CI fail is unrelated, this ins rebased and I added a test for the vfs - I'm a little surprised that I don't see the changes when I run the extension in dev mode, and I can't attach to the LSP. So I'm not sure if I just have a borked local vscode (which could be very possible) or it only works in tests and not reality :D So I'll try look on another computer to validate |
Hey @orta, very nice that you've spent some time on this again so quickly :) It would def. take me a while to get at speed with this. I've just cloned, compiled, ran the tests etc. :) It was a liiitle bit of a bumpy road for me as I'm dealing with the vscode codebase for the first time :D So, yeah, I have a bit of experience with the tooling etc. and just delved into the GitHub actions command to pave my way thru the jungle of what I need to get everything up and running locally in dev mode ;) Finally, I've got it working after an hour or so :)) Here are my current test results: Verified to actually work in reality, yay! 💯 Collides with this branch of reality :D Auto-complete on (local) file paths In case you'd like me to test more you, I'm very open to do so if you'd like to give me some exact instructions. Thanks alot! |
Yeah, cool, that is basically the same experience as without this PR, thanks. So, I've definitely broke it in |
@orta I think I've identified the issue - the Edit: To be clear I'm not sure if |
Heads up, I've opened a PR that should address this same issue: #193590 |
Is this still relevant? |
Re: #26338
I'm not sure it completes every feature requested in #26338 so I'm not marking this PR as fixing it, it might, but I don't have enough tests to verify it - but it does solve the one I really wanted: resolving JS Doc import types inside the script tags.
This PR switches just the TSServer to support reaching into the file-system in HTML-language-features giving TypeScript the chance to handle types across file boundaries.
Auto-complete for imports
Grabbing globals from
@types