-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Avoid crash for import code fixes with dotted require #47433
Conversation
… require(...) and require(...).foo.
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 fix seems good, I just don't like the new name at all.
I suggested a slightly less bad name, although it's still not good.
src/compiler/types.ts
Outdated
@@ -4668,6 +4668,11 @@ namespace ts { | |||
readonly initializer: RequireOrImportCall; | |||
} | |||
|
|||
/* @internal */ | |||
export interface AccessedOrBareRequireVariableDeclaration extends VariableDeclaration { |
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 think I prefer RequireVariableDeclarationOrExpression
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'd agree (less easy to miss if you're doing completion and were about to use the old one, too).
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’s not a “declaration or expression” though—it’s always a variable declaration, and the initializer of that variable declaration is always an expression. The thing that changes is whether that expression is a special call expression or a property access expression off that special call expression. I don’t like either of these names and don’t have a better suggestion ready, but I don’t understand what RequireVariableDeclarationOrExpression
is supposed to mean.
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 think I'm going to go with VariableDeclarationInitializedTo<T>
with CallExpression
and AccessExpression | CallExpression
.
src/compiler/types.ts
Outdated
@@ -4668,6 +4668,11 @@ namespace ts { | |||
readonly initializer: RequireOrImportCall; | |||
} | |||
|
|||
/* @internal */ | |||
export interface AccessedOrBareRequireVariableDeclaration extends VariableDeclaration { |
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'd agree (less easy to miss if you're doing completion and were about to use the old one, too).
I've renamed both functions uniformly so you can't miss them, though I've left |
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.
Seems okay to me, but someone else may object to the naming, of course.
@typescript-bot cherry-pick this to release-4.5 |
Heya @DanielRosenwasser, I've started to run the task to cherry-pick this into |
Hey @DanielRosenwasser, I've opened #47515 for you. |
Component commits: fce282b Add failing test. ea2c290 Update failing test. d954948 Finalized failing test case. f476e84 Separate our usages of utilities that expect variables initialized to require(...) and require(...).foo. 9f0810c Renamed types and utilities, removed accidental indentation. bf708bf Renamed both utilitiy functions uniformly.
Component commits: fce282b Add failing test. ea2c290 Update failing test. d954948 Finalized failing test case. f476e84 Separate our usages of utilities that expect variables initialized to require(...) and require(...).foo. 9f0810c Renamed types and utilities, removed accidental indentation. bf708bf Renamed both utilitiy functions uniformly. Co-authored-by: Daniel Rosenwasser <[email protected]>
Fixes #47428.
Okay, here's the summary:
First, we have a type predicate in our services layer that determines whether something is an
import
statement or a variable initialized with arequire
call.TypeScript/src/services/utilities.ts
Line 2032 in 0f1496f
That type predicate is wrong because it takes a dependency on
isRequireVariableStatement
...TypeScript/src/compiler/utilities.ts
Lines 2123 to 2127 in 0f1496f
which relies on
isRequireVariableDeclaration
...TypeScript/src/compiler/utilities.ts
Lines 2116 to 2121 in 0f1496f
which returns
true
a variable like inconst foo = require("yadda").foo
.Because the type predicate is wrong, we eventually end up crashing because we think we have a
CallExpression
on the initializer and can't access the first argument, resulting in:So my solution here is to split up the usages of the function - some for when a consumer can tolerate the property access version (
require("yadda").foo
), and some for tolerating the barerequire("yadda")
version.isRequireVariableStatement
can safely be changed to rely on the bare version because it's only called by the type predicate function.This at the very least avoids crashing for code-fixes without impacting go-to-definition, and other functionality in the type-checker itself.