Skip to content

Enable allowJs when inferred project has root JS files#3432

Draft
jakebailey wants to merge 5 commits intomainfrom
jabaile/fix-2621
Draft

Enable allowJs when inferred project has root JS files#3432
jakebailey wants to merge 5 commits intomainfrom
jabaile/fix-2621

Conversation

@jakebailey
Copy link
Copy Markdown
Member

Fixes #2621

See also: #2621 (comment)

This required introducing a @noDefaultOpen harness option, so that our fourslash runner doesn't open every file and cause our tests to not actually test "js exists but was not clicked into". The original fourslash runner worked directly on the language service without a server, so never hit this as there was no concept of "open".

That being said, it's a little unclear how the server was working so well in JS code without this code?

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes inferred-project behavior for unconfigured JavaScript files by ensuring allowJs is enabled when an inferred project’s roots include JS files, and adjusts the fourslash harness so tests can precisely control which files are “opened” (and thus become inferred roots).

Changes:

  • Enable AllowJs (and AllowNonTsExtensions) for inferred projects whenever any inferred root file is a JS-family extension.
  • Add a fourslash harness option @noDefaultOpen plus an exported OpenFile helper to avoid auto-opening every test file.
  • Update/select manual fourslash tests to use @noDefaultOpen and add a new regression test for completions in an unconfigured .js file.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
internal/testutil/harnessutil/harnessutil.go Adds NoDefaultOpen harness option parsing so tests can opt out of default didOpen behavior.
internal/project/projectcollectionbuilder.go Forces AllowJs when inferred roots include JS while updating inferred project roots.
internal/project/project.go Adds helpers to detect JS roots and clone compiler options with AllowJs enabled; applies in inferred project creation.
internal/fourslash/fourslash.go Implements @noDefaultOpen behavior in NewFourslash, marks openFile as helper, and exposes OpenFile.
internal/fourslash/tests/completionsInUnconfiguredJSFile_test.go New regression test validating completion works in an unconfigured .js file.
internal/fourslash/tests/manual/tripleSlashRefPathCompletionExtensionsAllowJSFalse_test.go Uses @noDefaultOpen and explicit open to prevent unintended inferred roots.
internal/fourslash/tests/manual/tripleSlashRefPathCompletionAbsolutePaths_test.go Uses @noDefaultOpen and explicit open to prevent unintended inferred roots.
internal/fourslash/tests/manual/completionForStringLiteralNonrelativeImport2_test.go Uses @noDefaultOpen and explicit opens for deterministic inferred roots.
internal/fourslash/_scripts/manualTests.txt Adds missing manual test entries so the manual test harness script includes them.

Comment thread internal/fourslash/fourslash.go Outdated
Comment on lines +902 to +906
// OpenFile opens a file via LSP didOpen, making it a root of the inferred project.
func (f *FourslashTest) OpenFile(t *testing.T, filename string) {
t.Helper()
f.openFile(t, filename)
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

The doc comment for OpenFile is a bit too strong: didOpen doesn’t necessarily make a file a root of the inferred project (if the file ends up belonging to a configured project, it won’t become an inferred root). Consider rewording to describe it as “opens a file via LSP didOpen” and, if relevant, note that it may affect inferred project roots when the file is unconfigured.

Copilot uses AI. Check for mistakes.
Comment thread internal/fourslash/fourslash.go Outdated
@andrewbranch
Copy link
Copy Markdown
Member

That being said, it's a little unclear how the server was working so well in JS code without this code?

Hm, is compilerOptionsForInferredProjects actually getting sent by default? The hard coded default compiler options for inferred projects has AllowJs enabled.

@jakebailey
Copy link
Copy Markdown
Member Author

It is right at startup, but the options it sends do not include allowJs; I don't think they did in Strada either, and it overrode the compiler options to force these two options on. Could be that we just need to undo that initial step, it's just really wonky given that corsa, strada fourslash, strada fourslash-server all behave differently

@andrewbranch
Copy link
Copy Markdown
Member

LGTM but generate is failing

Comment thread internal/fourslash/fourslash.go Outdated
if testData.isStateBaseliningEnabled() {
// Single baseline, so initialize project state baseline too
f.stateBaseline = newStateBaseline(fsFromMap.(iovfs.FsWithSys))
} else if harnessOptions.NoDefaultOpen {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm sure some state baseline tests probably could use this instead, but not worth the hassle right now.

@DanielRosenwasser
Copy link
Copy Markdown
Member

DanielRosenwasser commented Apr 17, 2026

Why don't we just enable allowJs for inferred projects without adjustments based on root files?

@jakebailey
Copy link
Copy Markdown
Member Author

We can do that, though I think we still need to force it on like Strada did, lest someone configure the inferred project manually, which is more or less the problem fourslash has.

@jakebailey
Copy link
Copy Markdown
Member Author

Oh, I'm dumb, the tests I'm referring to are tests which are explicitly trying to test behavior when allowJs is off. Maybe these tests are just bunk

@jakebailey
Copy link
Copy Markdown
Member Author

Here's an example of a fun one:

--- old.goToDefinitionCSSPatternAmbientModule.baseline.jsonc
+++ new.goToDefinitionCSSPatternAmbientModule.baseline.jsonc
@@= skipped -1, +1 lines =@@
 // === /index.css ===
 // [||]html { font-size: 16px; }

-// === /types.ts ===
-// <|declare module [|"*.css"|] {
-//   const styles: any;
-//   export = styles;
-// }|>
-
 // === /index.ts ===
 // import styles from /*GOTO DEF*/[|"./index.css"|];

We turn on both allowJs and allowNonTsExtensions, and this is an inferred project, so then we for some reason decide to not go to the types file anymore. (I'm not sure why the .css file is even selected before).

@andrewbranch
Copy link
Copy Markdown
Member

Why don't we just enable allowJs for inferred projects without adjustments based on root files?

Good question—root files are only opened files, so if you only open foo.ts but that imports ./bar.js (which is really a JS file with no TS / declaration file), is that an error?

@DanielRosenwasser
Copy link
Copy Markdown
Member

if you only open foo.ts but that imports ./bar.js (which is really a JS file with no TS / declaration file), is that an error?

Probably not. Any editors should probably set allowJs for unconfigured project settings, so we should probably just make that our default too.

@jakebailey
Copy link
Copy Markdown
Member Author

We actually do not yet support client setting any compiler options.

@andrewbranch
Copy link
Copy Markdown
Member

Yeah, confirmed that session.compilerOptionsForInferredProjects is never set in real life, only in fourslash. So in real VS Code, we're just using the default options in project.go, which always has --allowJs.

@jakebailey
Copy link
Copy Markdown
Member Author

Yeah, so this isn't really pressing to fix, thankfully.

I'm going to look harder and see if it's possible for us to massage our current tests to use the defaults somehow.

We do need to add support for the VS Code options that set these defaults, though.

@jakebailey jakebailey marked this pull request as draft April 17, 2026 23:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fourslash is broken when making requests in unconfigured .js files

4 participants