mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Add flag to skip qualification check when symbol is already in the process of being qualified (#21337)
This commit is contained in:
parent
a6d7a38c34
commit
ba797f2c50
@ -2424,12 +2424,15 @@ namespace ts {
|
||||
const visitedSymbolTables: SymbolTable[] = [];
|
||||
return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable);
|
||||
|
||||
function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable): Symbol[] | undefined {
|
||||
/**
|
||||
* @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already)
|
||||
*/
|
||||
function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable, ignoreQualification?: boolean): Symbol[] | undefined {
|
||||
if (!pushIfUnique(visitedSymbolTables, symbols)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result = trySymbolTable(symbols);
|
||||
const result = trySymbolTable(symbols, ignoreQualification);
|
||||
visitedSymbolTables.pop();
|
||||
return result;
|
||||
}
|
||||
@ -2441,22 +2444,22 @@ namespace ts {
|
||||
!!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing);
|
||||
}
|
||||
|
||||
function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol) {
|
||||
function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol, ignoreQualification?: boolean) {
|
||||
return symbol === (resolvedAliasSymbol || symbolFromSymbolTable) &&
|
||||
// if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table)
|
||||
// and if symbolFromSymbolTable or alias resolution matches the symbol,
|
||||
// check the symbol can be qualified, it is only then this symbol is accessible
|
||||
!some(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) &&
|
||||
canQualifySymbol(symbolFromSymbolTable, meaning);
|
||||
(ignoreQualification || canQualifySymbol(symbolFromSymbolTable, meaning));
|
||||
}
|
||||
|
||||
function isUMDExportSymbol(symbol: Symbol) {
|
||||
return symbol && symbol.declarations && symbol.declarations[0] && isNamespaceExportDeclaration(symbol.declarations[0]);
|
||||
}
|
||||
|
||||
function trySymbolTable(symbols: SymbolTable) {
|
||||
function trySymbolTable(symbols: SymbolTable, ignoreQualification: boolean | undefined) {
|
||||
// If symbol is directly available by its name in the symbol table
|
||||
if (isAccessible(symbols.get(symbol.escapedName))) {
|
||||
if (isAccessible(symbols.get(symbol.escapedName), /*resolvedAliasSymbol*/ undefined, ignoreQualification)) {
|
||||
return [symbol];
|
||||
}
|
||||
|
||||
@ -2469,14 +2472,14 @@ namespace ts {
|
||||
&& (!useOnlyExternalAliasing || some(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration))) {
|
||||
|
||||
const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable);
|
||||
if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol)) {
|
||||
if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) {
|
||||
return [symbolFromSymbolTable];
|
||||
}
|
||||
|
||||
// Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain
|
||||
// but only if the symbolFromSymbolTable can be qualified
|
||||
const candidateTable = getExportsOfSymbol(resolvedImportedSymbol);
|
||||
const accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable);
|
||||
const accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, /*ignoreQualification*/ true);
|
||||
if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) {
|
||||
return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports);
|
||||
}
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
//// [tests/cases/compiler/moduleDeclarationExportStarShadowingGlobalIsNameable.ts] ////
|
||||
|
||||
//// [index.ts]
|
||||
export * from "./account";
|
||||
|
||||
//// [account.ts]
|
||||
export interface Account {
|
||||
myAccNum: number;
|
||||
}
|
||||
interface Account2 {
|
||||
myAccNum: number;
|
||||
}
|
||||
export { Account2 as Acc };
|
||||
|
||||
//// [index.ts]
|
||||
declare global {
|
||||
interface Account {
|
||||
someProp: number;
|
||||
}
|
||||
interface Acc {
|
||||
someProp: number;
|
||||
}
|
||||
}
|
||||
import * as model from "./model";
|
||||
export const func = (account: model.Account, acc2: model.Acc) => {};
|
||||
|
||||
|
||||
//// [account.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
//// [index.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
//// [index.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.func = function (account, acc2) { };
|
||||
|
||||
|
||||
//// [account.d.ts]
|
||||
export interface Account {
|
||||
myAccNum: number;
|
||||
}
|
||||
interface Account2 {
|
||||
myAccNum: number;
|
||||
}
|
||||
export { Account2 as Acc };
|
||||
//// [index.d.ts]
|
||||
export * from "./account";
|
||||
//// [index.d.ts]
|
||||
declare global {
|
||||
interface Account {
|
||||
someProp: number;
|
||||
}
|
||||
interface Acc {
|
||||
someProp: number;
|
||||
}
|
||||
}
|
||||
import * as model from "./model";
|
||||
export declare const func: (account: model.Account, acc2: model.Acc) => void;
|
||||
@ -0,0 +1,49 @@
|
||||
=== tests/cases/compiler/model/index.ts ===
|
||||
export * from "./account";
|
||||
No type information for this code.
|
||||
No type information for this code.=== tests/cases/compiler/model/account.ts ===
|
||||
export interface Account {
|
||||
>Account : Symbol(Account, Decl(account.ts, 0, 0))
|
||||
|
||||
myAccNum: number;
|
||||
>myAccNum : Symbol(Account.myAccNum, Decl(account.ts, 0, 26))
|
||||
}
|
||||
interface Account2 {
|
||||
>Account2 : Symbol(Account2, Decl(account.ts, 2, 1))
|
||||
|
||||
myAccNum: number;
|
||||
>myAccNum : Symbol(Account2.myAccNum, Decl(account.ts, 3, 20))
|
||||
}
|
||||
export { Account2 as Acc };
|
||||
>Account2 : Symbol(Acc, Decl(account.ts, 6, 8))
|
||||
>Acc : Symbol(Acc, Decl(account.ts, 6, 8))
|
||||
|
||||
=== tests/cases/compiler/index.ts ===
|
||||
declare global {
|
||||
>global : Symbol(global, Decl(index.ts, 0, 0))
|
||||
|
||||
interface Account {
|
||||
>Account : Symbol(Account, Decl(index.ts, 0, 16))
|
||||
|
||||
someProp: number;
|
||||
>someProp : Symbol(Account.someProp, Decl(index.ts, 1, 23))
|
||||
}
|
||||
interface Acc {
|
||||
>Acc : Symbol(Acc, Decl(index.ts, 3, 5))
|
||||
|
||||
someProp: number;
|
||||
>someProp : Symbol(Acc.someProp, Decl(index.ts, 4, 19))
|
||||
}
|
||||
}
|
||||
import * as model from "./model";
|
||||
>model : Symbol(model, Decl(index.ts, 8, 6))
|
||||
|
||||
export const func = (account: model.Account, acc2: model.Acc) => {};
|
||||
>func : Symbol(func, Decl(index.ts, 9, 12))
|
||||
>account : Symbol(account, Decl(index.ts, 9, 21))
|
||||
>model : Symbol(model, Decl(index.ts, 8, 6))
|
||||
>Account : Symbol(model.Account, Decl(account.ts, 0, 0))
|
||||
>acc2 : Symbol(acc2, Decl(index.ts, 9, 44))
|
||||
>model : Symbol(model, Decl(index.ts, 8, 6))
|
||||
>Acc : Symbol(model.Acc, Decl(account.ts, 6, 8))
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
=== tests/cases/compiler/model/index.ts ===
|
||||
export * from "./account";
|
||||
No type information for this code.
|
||||
No type information for this code.=== tests/cases/compiler/model/account.ts ===
|
||||
export interface Account {
|
||||
>Account : Account
|
||||
|
||||
myAccNum: number;
|
||||
>myAccNum : number
|
||||
}
|
||||
interface Account2 {
|
||||
>Account2 : Account2
|
||||
|
||||
myAccNum: number;
|
||||
>myAccNum : number
|
||||
}
|
||||
export { Account2 as Acc };
|
||||
>Account2 : any
|
||||
>Acc : any
|
||||
|
||||
=== tests/cases/compiler/index.ts ===
|
||||
declare global {
|
||||
>global : any
|
||||
|
||||
interface Account {
|
||||
>Account : Account
|
||||
|
||||
someProp: number;
|
||||
>someProp : number
|
||||
}
|
||||
interface Acc {
|
||||
>Acc : Acc
|
||||
|
||||
someProp: number;
|
||||
>someProp : number
|
||||
}
|
||||
}
|
||||
import * as model from "./model";
|
||||
>model : typeof model
|
||||
|
||||
export const func = (account: model.Account, acc2: model.Acc) => {};
|
||||
>func : (account: model.Account, acc2: model.Acc) => void
|
||||
>(account: model.Account, acc2: model.Acc) => {} : (account: model.Account, acc2: model.Acc) => void
|
||||
>account : model.Account
|
||||
>model : any
|
||||
>Account : model.Account
|
||||
>acc2 : model.Acc
|
||||
>model : any
|
||||
>Acc : model.Acc
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
// @declaration: true
|
||||
// @filename: model/index.ts
|
||||
export * from "./account";
|
||||
|
||||
// @filename: model/account.ts
|
||||
export interface Account {
|
||||
myAccNum: number;
|
||||
}
|
||||
interface Account2 {
|
||||
myAccNum: number;
|
||||
}
|
||||
export { Account2 as Acc };
|
||||
|
||||
// @filename: index.ts
|
||||
declare global {
|
||||
interface Account {
|
||||
someProp: number;
|
||||
}
|
||||
interface Acc {
|
||||
someProp: number;
|
||||
}
|
||||
}
|
||||
import * as model from "./model";
|
||||
export const func = (account: model.Account, acc2: model.Acc) => {};
|
||||
Loading…
x
Reference in New Issue
Block a user