This is a large refactor of project system code in preparation for the packages work.
This aims to collapse a lot of types across the JS/VSCode/WASM/compiler layers that are similar-but-not-quite the same. I did end up getting rid of a lot of types, but in some places confusion is unavoidable (e.g. ProjectConfig vs ProgramConfig). I tried to document those places as much as possible.
Highlights
🎉 Get rid of the deprecated overloads in ICompiler
🎊 Replace a bunch of separately-passed-in callbacks in the WASM layer with a trait and eliminate a lot of layers to plumb those callbacks through ProjectLoader, LanguageService, etc. This also eliminates the need for some complex macros and manually-defined types such as type AsyncFunction<'a, Arg, Return> = Box<dyn Fn(Arg) -> PinnedFuture<Return> + 'a>
🍾 Define a ProgramConfig type to group the compiler-related parameters that are commonly passed into the WASM functions, so we don't have to update 1,000,000 spots when we add a new compiler setting, or, say, package support.
🙌 Consolidate FileSystem and FileSystemAsync
🥳 The manifest is now consistently parsed in the native layer, rather than the parsing sometimes being done in JS.
Changes by layer:
qsc_project
Consolidate FileSystem and FileSystemAsync implementations by making one call the other. Previously, we had two copies of the implementation, one sync and one async - and they're about to get a lot more complicated with packages work. So I tried an approach where the sync implementation just wraps the async one.
This also means that the async feature is no longer optional in this crate.
Define a trait, JSProjectHost, to define the manifest/filesystem functions, instead of using a struct with callbacks. This helped get rid of a lot of boxed async function types we were having to store in different places, and replaced them with more intuitive trait impls.
The manifest is now being parsed in the native layer instead of JS. Hopefully this will centralize our error handling a bit and make behavior more consistent across scenarios (Python, JS). It also lays the groundwork for package dependencies, where we'll have to parse dependency manifests in the native layer anyway.
The project loading code now returns the name and manifest_path, values which are used in various extension features. Previously these values were being generated JS-side, but it makes sense to populate them at the point we're loading the project.
language_service
Call the new find_manifest_directory host function instead of get_manifest which used to do the manifest parsing JS-side.
Remove the project system callbacks in favor of the unified JSProjectHost trait.
Remove LoadManifestResult in favor of the Project type already defined in qsc_project
Tests: Split out the in-memory FS used in a few different tests, to a shared module test_fs.
npm
Get rid of the deprecated overloads in ICompiler. QCOM has already been updated to use the new signatures.
Where applicable, ICompiler and IDebugService methods all take a consistent ProgramConfig type, which contains the sources and compiler settings, which also has a straightforward conversion to the type used in the WASM crate.
Verified backcompat with QCOM. (IDebugService is a breaking change but it's not used anywhere but VS Code).
pip
Only change here is to trivially plumb through the new resolve_path filesystem method.
vscode
Fix up the various spots where the ICompiler methods were updated to take ProgramConfig.
We don't parse the manifest in the VS Code layer anymore. Instead we just discover it (in findManifestDirectory), and the native code does all the rest.
wasm
Consolidate parameters such as sources, language_features, target_profile into one ProgramConfig type. This is almost the same as the ProgramConfig in compiler.ts , except this one is more strictly typed since backcompat isn't a concern.
Remove tons of code that was needed make the async JS callbacks work, replacing it with a wasm-bindgen attributes where applicable, and using a trait instead of separate callbacks.
This is a large refactor of project system code in preparation for the packages work.
This aims to collapse a lot of types across the JS/VSCode/WASM/compiler layers that are similar-but-not-quite the same. I did end up getting rid of a lot of types, but in some places confusion is unavoidable (e.g.
ProjectConfig
vsProgramConfig
). I tried to document those places as much as possible.Highlights
ICompiler
ProjectLoader
,LanguageService
, etc. This also eliminates the need for some complex macros and manually-defined types such astype AsyncFunction<'a, Arg, Return> = Box<dyn Fn(Arg) -> PinnedFuture<Return> + 'a>
ProgramConfig
type to group the compiler-related parameters that are commonly passed into the WASM functions, so we don't have to update 1,000,000 spots when we add a new compiler setting, or, say, package support.FileSystem
andFileSystemAsync
Changes by layer:
qsc_project
FileSystem
andFileSystemAsync
implementations by making one call the other. Previously, we had two copies of the implementation, one sync and one async - and they're about to get a lot more complicated with packages work. So I tried an approach where the sync implementation just wraps theasync
one.async
feature is no longer optional in this crate.JSProjectHost
, to define the manifest/filesystem functions, instead of using a struct with callbacks. This helped get rid of a lot of boxed async function types we were having to store in different places, and replaced them with more intuitive trait impls.name
andmanifest_path
, values which are used in various extension features. Previously these values were being generated JS-side, but it makes sense to populate them at the point we're loading the project.language_service
find_manifest_directory
host function instead ofget_manifest
which used to do the manifest parsing JS-side.JSProjectHost
trait.LoadManifestResult
in favor of theProject
type already defined inqsc_project
test_fs
.npm
ICompiler
. QCOM has already been updated to use the new signatures.ICompiler
andIDebugService
methods all take a consistentProgramConfig
type, which contains the sources and compiler settings, which also has a straightforward conversion to the type used in the WASM crate.IDebugService
is a breaking change but it's not used anywhere but VS Code).pip
resolve_path
filesystem method.vscode
ICompiler
methods were updated to takeProgramConfig
.findManifestDirectory
), and the native code does all the rest.wasm
sources
,language_features
,target_profile
into oneProgramConfig
type. This is almost the same as theProgramConfig
in compiler.ts , except this one is more strictly typed since backcompat isn't a concern.wasm-bindgen
attributes where applicable, and using atrait
instead of separate callbacks.