-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Add --allowArbitraryExtensions
, a flag for allowing arbitrary extensions on import paths
#51435
Add --allowArbitraryExtensions
, a flag for allowing arbitrary extensions on import paths
#51435
Conversation
A name suggestion: How about |
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 all seems good and straightforward to me; mostly test changes and the actual changes are really nice and minimal.
My only question is about performance; we're doing quick checks to avoid extra FS calls, right?
src/compiler/parser.ts
Outdated
@@ -9775,7 +9776,7 @@ namespace IncrementalParser { | |||
|
|||
/** @internal */ | |||
export function isDeclarationFileName(fileName: string): boolean { | |||
return fileExtensionIsOneOf(fileName, supportedDeclarationExtensions); | |||
return fileExtensionIsOneOf(fileName, supportedDeclarationExtensions) || (fileExtensionIs(fileName, Extension.Ts) && stringContains(fileName, ".d.")); |
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.
I guess we're going so far as to support foo.d.tar.gz.ts
? i.e. multiple dots?
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.
Right now we interpret such a name as a declaration file, but will never match it, since we only consider everything after the last dot for the extracted extension. Somewhat on the fence about it right now tbh - I dunno if we need to handle compound extensions or not. Maybe I should adjust the lookup logic so it does?
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.
I honestly have no clue. It seems like someone's going to try to do it... but maybe not?
Yeah, we only do the new fs check when the extension in the import isn't a TS or JS one. |
I’ve only just glanced at the implementation, but re: naming—in #51171 I introduce
To that end, I would like to brainstorm flag names that don’t seem to imply |
Also: don’t you need corresponding changes in moduleSpecifiers.ts and path completions? E.g., what happens in declaration emit when you have: // foo.d.html.ts
export declare class CustomHtmlRepresentationThing {}
export declare const someHtml: CustomHtmlRepresentationThing;
// index.ts
import { someHtml } from "./foo.html";
export function getHtml() {
return someHtml;
} |
@andrewbranch Done - I've also simplified things in the module name resolver quite a bit, in part thanks to your refactorings. As an added bonus, |
@@ -444,6 +450,8 @@ FsWatches:: | |||
{} | |||
|
|||
FsWatchesRecursive:: | |||
/user/username/projects/myproject/lib1: |
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.
Just as an FYI, all these extra watchers are here because these tests have an import that looks like "./tools/tools.interface"
which now looks for a ./tools/tools.d.interface.ts
(for the potential literal tools.interface
file) before adding a .js
or .ts
extension onto the import to find what it currently finds. The additional failed lookup location triggers adding a directory watcher, since now a new file may appear which changes the resolution result~
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.
can you instead change the test to import "./tools/toolsInterface" since the extension part is irrelevant for these tests?
|
||
import z from "./z.d.ts"; | ||
>z : any | ||
>z : number |
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.
It is probably worth noting that while these types refering to a ts source file in the import do now resolve, the error on the import is still present - it's just added in the checker even on successful resolution now.
I’ve already done this too 😅 let the merge conflicts continue! |
src/compiler/checker.ts
Outdated
@@ -4753,6 +4753,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { | |||
} | |||
} | |||
} | |||
|
|||
if (moduleNotFoundError) { | |||
if (tryGetExtensionFromPath(sourceFile.fileName) === tryGetExtensionFromPath(moduleReference)) { |
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.
Doesn’t this falsely trigger on import {} from "./foo.ts"
when the source file is foo.ts.ts
? In my implementation, I couldn’t find a better way than to add a property onto ResolvedModule
that indicated whether the .ts
extension was actually used to match a .ts
file extension.
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 error says that the "import path can't end in .ts
" not that it can't resolve to TS, so I'd argue it's not a false positive. Honestly, a "./foo.ts"
that resolves to "./foo.ts.js"
is expempted from the error right now, but I'm questioning more if that's OK - blanket saying "relative import specifiers can't end in .ts unless you pass some flag" just seems easier to understand, and covers weird cjs corners like this, if overzealously.
@@ -444,6 +450,8 @@ FsWatches:: | |||
{} | |||
|
|||
FsWatchesRecursive:: | |||
/user/username/projects/myproject/lib1: |
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.
can you instead change the test to import "./tools/toolsInterface" since the extension part is irrelevant for these tests?
@@ -43,6 +43,9 @@ | |||
"File '/node_modules/exports-and-types-versions/package.json' exists according to earlier cached lookups.", | |||
"Matched 'exports' condition 'types'.", | |||
"Using 'exports' subpath './yep' with target './types/foo.d.ts'.", | |||
"File name '/node_modules/exports-and-types-versions/types/foo.d.ts' has a '.d.ts' extension - stripping it.", | |||
"File '/node_modules/exports-and-types-versions/types/foo.ts' does not exist.", |
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.
These checks seem non intuitive. When types or exports entry already has "d.ts" extension and we are saying we prefer ".ts" over ".d.ts" even though field said to use ".d.ts" .. Just more configuration error prone i think.
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 generally true all the time - .ts
files that correspond to a .d.ts
file are higher priority than the .d.ts
file, even if your path explicitly uses the .d.ts
extension. This is basically to mirror our wildcard include behavior which likewise prefers the .ts
file to the .d.ts
file.
…s on import paths
17e1a6b
to
b1fe76f
Compare
@andrewbranch conflicts resolved, there's a minor change in the |
--allowNonJsExtensions
, a flag for allowing arbitrary extensions on import paths--allowArbitraryExtensions
, a flag for allowing arbitrary extensions on import paths
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.
Not an expert but the code seems fine to me; I think the new name is fine as well. (I'm guessing Andrew will look click a button too but here's my click.)
}; | ||
const lib1ToolsInterface: File = { | ||
path: `/user/username/projects/myproject/lib1/tools/tools.interface.ts`, | ||
path: `/user/username/projects/myproject/lib1/tools/toolsinterface.ts`, |
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.
Are filenames like this problematic now?
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.
No, they just add a (higher priority) lookup location which has knock-on effects regarding file watchers in the baseline, so to avoid baseline noise Sheetal asked I simply change the filename.
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.
Looks good once moduleResolutionSupportsResolvingTsExtensions
is deleted.
@andrewbranch done~ |
{ | ||
name: "allowArbitraryExtensions", | ||
type: "boolean", | ||
affectsModuleResolution: true, |
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.
I was gathering module-resolution-affecting compiler options for docs, and noticed this. AFAICT it doesn’t affect module resolution, just whether an error is issued. This should probably be swapped for affectsSemanticDiagnostics
.
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.
Is this something that should be in 5.0 beta? I just got to this comment in my email and noticed a PR wasn't sent for this (but I don't know how these two settings matter myself)
It just means we're over-invalidating incremental builds a little bit,
since we're tossing resolutions that we could probably reuse if the option
value is changed. Honestly not too high impact, so we don't need to squeeze
it into the beta if it'll delay things, but we can probably ship a fix in
the rc no problem, since a fix is just changing the field name here to
another one.
…On Thu, Jan 26, 2023, 11:40 AM Jake Bailey ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/compiler/commandLineParser.ts
<#51435 (comment)>
:
> @@ -1206,6 +1206,14 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
description: Diagnostics.Enable_importing_json_files,
defaultValueDescription: false,
},
+ {
+ name: "allowArbitraryExtensions",
+ type: "boolean",
+ affectsModuleResolution: true,
Is this something that should be in 5.0 beta? I just got to this comment
in my email and noticed a PR wasn't sent for this (but I don't know how
these two settings matter myself)
—
Reply to this email directly, view it on GitHub
<#51435 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAWMAMTG6YIP7AQ4B6R4WSTWULHMLANCNFSM6AAAAAARZXVPPM>
.
You are receiving this because you modified the open/close state.Message
ID: ***@***.***>
|
I sent #52437 for it just to have it off of my mind 😅 |
Apart from incremental build, it also means that source files are not reused in LS if |
And, correspondingly, the
.d.ext.ts
files needed to describe the shape of whatever it is your importing.Implements #50133
Option name, as always, open to 🚴🏚️.