mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Improve valueDeclaration for js module merges (#24707)
Nearly everything in a merge of JS special assignments looks like a
valueDeclaration. This commit ensures that intermediate "module
declarations" are not used when a better valueDeclaration is available:
```js
// File1.js
var X = {}
X.Y.Z = class { }
// File2.js
X.Y = {}
```
In the above example, the `Y` in `X.Y.Z = class { }` was used as the
valueDeclaration for `Y` because it appeared before `X.Y = {}` in the
compilation.
This change exposed a bug in binding, #24703, that required a change in
typeFromPropertyAssignmentOutOfOrder. The test still fails for the
original reason it was created, and the new bug #24703 contains a repro.
This commit is contained in:
@@ -236,7 +236,7 @@ namespace ts {
|
||||
if (symbolFlags & SymbolFlags.Value) {
|
||||
const { valueDeclaration } = symbol;
|
||||
if (!valueDeclaration ||
|
||||
(valueDeclaration.kind !== node.kind && valueDeclaration.kind === SyntaxKind.ModuleDeclaration)) {
|
||||
(valueDeclaration.kind !== node.kind && isEffectiveModuleDeclaration(valueDeclaration))) {
|
||||
// other kinds of value declarations take precedence over modules
|
||||
symbol.valueDeclaration = node;
|
||||
}
|
||||
|
||||
@@ -921,7 +921,7 @@ namespace ts {
|
||||
target.flags |= source.flags;
|
||||
if (source.valueDeclaration &&
|
||||
(!target.valueDeclaration ||
|
||||
(target.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && source.valueDeclaration.kind !== SyntaxKind.ModuleDeclaration))) {
|
||||
isEffectiveModuleDeclaration(target.valueDeclaration) && !isEffectiveModuleDeclaration(source.valueDeclaration))) {
|
||||
// other kinds of value declarations take precedence over modules
|
||||
target.valueDeclaration = source.valueDeclaration;
|
||||
}
|
||||
|
||||
@@ -451,6 +451,16 @@ namespace ts {
|
||||
return isModuleDeclaration(node) && isStringLiteral(node.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* An effective module (namespace) declaration is either
|
||||
* 1. An actual declaration: namespace X { ... }
|
||||
* 2. A Javascript declaration, which is:
|
||||
* An identifier in a nested property access expression: Y in `X.Y.Z = { ... }`
|
||||
*/
|
||||
export function isEffectiveModuleDeclaration(node: Node) {
|
||||
return isModuleDeclaration(node) || isIdentifier(node);
|
||||
}
|
||||
|
||||
/** Given a symbol for a module, checks that it is a shorthand ambient module. */
|
||||
export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean {
|
||||
return isShorthandAmbientModule(moduleSymbol.valueDeclaration);
|
||||
|
||||
Reference in New Issue
Block a user