Skip to content

Commit 2627e6f

Browse files
authored
[Transforms] Merge master on 08/05 (#10182)
* Fix #10083 - allowSyntheticDefaultImports alters getExternalModuleMember (#10096) * Add a helper function `getOrUpdateProperty` to prevent unprotected access to Maps. * Limit type guards as assertions to incomplete types in loops * Accept new baselines * Fix linting error * [Release-2.0] Fix 9662: Visual Studio 2015 with TS2.0 gives incorrect @types path resolution errors (#9867) * Change the shape of the shim layer to support getAutomaticTypeDirectives * Change the key for looking up automatic type-directives * Update baselines from change look-up name of type-directives * Add @CurrentDirectory into the test * Update baselines * Fix linting error * Address PR: fix spelling mistake * Instead of return path of the type directive names just return type directive names * Remove unused reference files: these tests produce erros so they will not produce these files (#9233) * Don't allow properties inherited from Object to be automatically included in TSX attributes * Port PR #10016 to Master (#10100) * Treat namespaceExportDeclaration as declaration * Update baselines * wip - add tests * Add tests * Show "export namespace" for quick-info * Update baselines from merging
1 parent c725ee4 commit 2627e6f

File tree

83 files changed

+535
-966
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+535
-966
lines changed

src/compiler/checker.ts

+54-32
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ namespace ts {
216216
const flowLoopKeys: string[] = [];
217217
const flowLoopTypes: Type[][] = [];
218218
const visitedFlowNodes: FlowNode[] = [];
219-
const visitedFlowTypes: Type[] = [];
219+
const visitedFlowTypes: FlowType[] = [];
220220
const potentialThisCollisions: Node[] = [];
221221
const awaitedTypeStack: number[] = [];
222222

@@ -1136,6 +1136,10 @@ namespace ts {
11361136
else {
11371137
symbolFromVariable = getPropertyOfVariable(targetSymbol, name.text);
11381138
}
1139+
// If the export member we're looking for is default, and there is no real default but allowSyntheticDefaultImports is on, return the entire module as the default
1140+
if (!symbolFromVariable && allowSyntheticDefaultImports && name.text === "default") {
1141+
symbolFromVariable = resolveExternalModuleSymbol(moduleSymbol) || resolveSymbol(moduleSymbol);
1142+
}
11391143
// if symbolFromVariable is export - get its final target
11401144
symbolFromVariable = resolveSymbol(symbolFromVariable);
11411145
const symbolFromModule = getExportOfModule(targetSymbol, name.text);
@@ -8094,21 +8098,33 @@ namespace ts {
80948098
f(type) ? type : neverType;
80958099
}
80968100

8101+
function isIncomplete(flowType: FlowType) {
8102+
return flowType.flags === 0;
8103+
}
8104+
8105+
function getTypeFromFlowType(flowType: FlowType) {
8106+
return flowType.flags === 0 ? (<IncompleteType>flowType).type : <Type>flowType;
8107+
}
8108+
8109+
function createFlowType(type: Type, incomplete: boolean): FlowType {
8110+
return incomplete ? { flags: 0, type } : type;
8111+
}
8112+
80978113
function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, includeOuterFunctions: boolean) {
80988114
let key: string;
80998115
if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
81008116
return declaredType;
81018117
}
81028118
const initialType = assumeInitialized ? declaredType : includeFalsyTypes(declaredType, TypeFlags.Undefined);
81038119
const visitedFlowStart = visitedFlowCount;
8104-
const result = getTypeAtFlowNode(reference.flowNode);
8120+
const result = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode));
81058121
visitedFlowCount = visitedFlowStart;
81068122
if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull) === neverType) {
81078123
return declaredType;
81088124
}
81098125
return result;
81108126

8111-
function getTypeAtFlowNode(flow: FlowNode): Type {
8127+
function getTypeAtFlowNode(flow: FlowNode): FlowType {
81128128
while (true) {
81138129
if (flow.flags & FlowFlags.Shared) {
81148130
// We cache results of flow type resolution for shared nodes that were previously visited in
@@ -8120,7 +8136,7 @@ namespace ts {
81208136
}
81218137
}
81228138
}
8123-
let type: Type;
8139+
let type: FlowType;
81248140
if (flow.flags & FlowFlags.Assignment) {
81258141
type = getTypeAtFlowAssignment(<FlowAssignment>flow);
81268142
if (!type) {
@@ -8188,41 +8204,44 @@ namespace ts {
81888204
return undefined;
81898205
}
81908206

8191-
function getTypeAtFlowCondition(flow: FlowCondition) {
8192-
let type = getTypeAtFlowNode(flow.antecedent);
8207+
function getTypeAtFlowCondition(flow: FlowCondition): FlowType {
8208+
const flowType = getTypeAtFlowNode(flow.antecedent);
8209+
let type = getTypeFromFlowType(flowType);
81938210
if (type !== neverType) {
81948211
// If we have an antecedent type (meaning we're reachable in some way), we first
8195-
// attempt to narrow the antecedent type. If that produces the nothing type, then
8196-
// we take the type guard as an indication that control could reach here in a
8197-
// manner not understood by the control flow analyzer (e.g. a function argument
8198-
// has an invalid type, or a nested function has possibly made an assignment to a
8199-
// captured variable). We proceed by reverting to the declared type and then
8212+
// attempt to narrow the antecedent type. If that produces the never type, and if
8213+
// the antecedent type is incomplete (i.e. a transient type in a loop), then we
8214+
// take the type guard as an indication that control *could* reach here once we
8215+
// have the complete type. We proceed by reverting to the declared type and then
82008216
// narrow that.
82018217
const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0;
82028218
type = narrowType(type, flow.expression, assumeTrue);
8203-
if (type === neverType) {
8219+
if (type === neverType && isIncomplete(flowType)) {
82048220
type = narrowType(declaredType, flow.expression, assumeTrue);
82058221
}
82068222
}
8207-
return type;
8223+
return createFlowType(type, isIncomplete(flowType));
82088224
}
82098225

8210-
function getTypeAtSwitchClause(flow: FlowSwitchClause) {
8211-
const type = getTypeAtFlowNode(flow.antecedent);
8226+
function getTypeAtSwitchClause(flow: FlowSwitchClause): FlowType {
8227+
const flowType = getTypeAtFlowNode(flow.antecedent);
8228+
let type = getTypeFromFlowType(flowType);
82128229
const expr = flow.switchStatement.expression;
82138230
if (isMatchingReference(reference, expr)) {
8214-
return narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
8231+
type = narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
82158232
}
8216-
if (isMatchingPropertyAccess(expr)) {
8217-
return narrowTypeByDiscriminant(type, <PropertyAccessExpression>expr, t => narrowTypeBySwitchOnDiscriminant(t, flow.switchStatement, flow.clauseStart, flow.clauseEnd));
8233+
else if (isMatchingPropertyAccess(expr)) {
8234+
type = narrowTypeByDiscriminant(type, <PropertyAccessExpression>expr, t => narrowTypeBySwitchOnDiscriminant(t, flow.switchStatement, flow.clauseStart, flow.clauseEnd));
82188235
}
8219-
return type;
8236+
return createFlowType(type, isIncomplete(flowType));
82208237
}
82218238

8222-
function getTypeAtFlowBranchLabel(flow: FlowLabel) {
8239+
function getTypeAtFlowBranchLabel(flow: FlowLabel): FlowType {
82238240
const antecedentTypes: Type[] = [];
8241+
let seenIncomplete = false;
82248242
for (const antecedent of flow.antecedents) {
8225-
const type = getTypeAtFlowNode(antecedent);
8243+
const flowType = getTypeAtFlowNode(antecedent);
8244+
const type = getTypeFromFlowType(flowType);
82268245
// If the type at a particular antecedent path is the declared type and the
82278246
// reference is known to always be assigned (i.e. when declared and initial types
82288247
// are the same), there is no reason to process more antecedents since the only
@@ -8233,11 +8252,14 @@ namespace ts {
82338252
if (!contains(antecedentTypes, type)) {
82348253
antecedentTypes.push(type);
82358254
}
8255+
if (isIncomplete(flowType)) {
8256+
seenIncomplete = true;
8257+
}
82368258
}
8237-
return getUnionType(antecedentTypes);
8259+
return createFlowType(getUnionType(antecedentTypes), seenIncomplete);
82388260
}
82398261

8240-
function getTypeAtFlowLoopLabel(flow: FlowLabel) {
8262+
function getTypeAtFlowLoopLabel(flow: FlowLabel): FlowType {
82418263
// If we have previously computed the control flow type for the reference at
82428264
// this flow loop junction, return the cached type.
82438265
const id = getFlowNodeId(flow);
@@ -8249,12 +8271,12 @@ namespace ts {
82498271
return cache[key];
82508272
}
82518273
// If this flow loop junction and reference are already being processed, return
8252-
// the union of the types computed for each branch so far. We should never see
8253-
// an empty array here because the first antecedent of a loop junction is always
8254-
// the non-looping control flow path that leads to the top.
8274+
// the union of the types computed for each branch so far, marked as incomplete.
8275+
// We should never see an empty array here because the first antecedent of a loop
8276+
// junction is always the non-looping control flow path that leads to the top.
82558277
for (let i = flowLoopStart; i < flowLoopCount; i++) {
82568278
if (flowLoopNodes[i] === flow && flowLoopKeys[i] === key) {
8257-
return getUnionType(flowLoopTypes[i]);
8279+
return createFlowType(getUnionType(flowLoopTypes[i]), /*incomplete*/ true);
82588280
}
82598281
}
82608282
// Add the flow loop junction and reference to the in-process stack and analyze
@@ -8265,7 +8287,7 @@ namespace ts {
82658287
flowLoopTypes[flowLoopCount] = antecedentTypes;
82668288
for (const antecedent of flow.antecedents) {
82678289
flowLoopCount++;
8268-
const type = getTypeAtFlowNode(antecedent);
8290+
const type = getTypeFromFlowType(getTypeAtFlowNode(antecedent));
82698291
flowLoopCount--;
82708292
// If we see a value appear in the cache it is a sign that control flow analysis
82718293
// was restarted and completed by checkExpressionCached. We can simply pick up
@@ -10068,7 +10090,7 @@ namespace ts {
1006810090
for (const prop of props) {
1006910091
// Is there a corresponding property in the element attributes type? Skip checking of properties
1007010092
// that have already been assigned to, as these are not actually pushed into the resulting type
10071-
if (!nameTable[prop.name]) {
10093+
if (!hasProperty(nameTable, prop.name)) {
1007210094
const targetPropSym = getPropertyOfType(elementAttributesType, prop.name);
1007310095
if (targetPropSym) {
1007410096
const msg = chainDiagnosticMessages(undefined, Diagnostics.Property_0_of_JSX_spread_attribute_is_not_assignable_to_target_property, prop.name);
@@ -10414,7 +10436,7 @@ namespace ts {
1041410436
const targetProperties = getPropertiesOfType(targetAttributesType);
1041510437
for (let i = 0; i < targetProperties.length; i++) {
1041610438
if (!(targetProperties[i].flags & SymbolFlags.Optional) &&
10417-
nameTable[targetProperties[i].name] === undefined) {
10439+
!hasProperty(nameTable, targetProperties[i].name)) {
1041810440

1041910441
error(node, Diagnostics.Property_0_is_missing_in_type_1, targetProperties[i].name, typeToString(targetAttributesType));
1042010442
}
@@ -19845,7 +19867,7 @@ namespace ts {
1984519867
}
1984619868

1984719869
function checkGrammarTopLevelElementForRequiredDeclareModifier(node: Node): boolean {
19848-
// A declare modifier is required for any top level .d.ts declaration except export=, export default,
19870+
// A declare modifier is required for any top level .d.ts declaration except export=, export default, export as namespace
1984919871
// interfaces and imports categories:
1985019872
//
1985119873
// DeclarationElement:
@@ -19863,8 +19885,8 @@ namespace ts {
1986319885
node.kind === SyntaxKind.ImportEqualsDeclaration ||
1986419886
node.kind === SyntaxKind.ExportDeclaration ||
1986519887
node.kind === SyntaxKind.ExportAssignment ||
19888+
node.kind === SyntaxKind.NamespaceExportDeclaration ||
1986619889
getModifierFlags(node) & (ModifierFlags.Ambient | ModifierFlags.Export | ModifierFlags.Default)) {
19867-
1986819890
return false;
1986919891
}
1987019892

src/compiler/core.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -499,8 +499,12 @@ namespace ts {
499499
return keys;
500500
}
501501

502-
export function getProperty<T>(map: Map<T>, key: string): T {
503-
return hasOwnProperty.call(map, key) ? map[key] : undefined;
502+
export function getProperty<T>(map: Map<T>, key: string): T | undefined {
503+
return hasProperty(map, key) ? map[key] : undefined;
504+
}
505+
506+
export function getOrUpdateProperty<T>(map: Map<T>, key: string, makeValue: () => T): T {
507+
return hasProperty(map, key) ? map[key] : map[key] = makeValue();
504508
}
505509

506510
export function isEmpty<T>(map: Map<T>) {

src/compiler/program.ts

+9-10
Original file line numberDiff line numberDiff line change
@@ -1056,19 +1056,15 @@ namespace ts {
10561056
return resolutions;
10571057
}
10581058

1059-
function getInferredTypesRoot(options: CompilerOptions, rootFiles: string[], host: CompilerHost) {
1060-
return computeCommonSourceDirectoryOfFilenames(rootFiles, host.getCurrentDirectory(), f => host.getCanonicalFileName(f));
1061-
}
1062-
10631059
/**
1064-
* Given a set of options and a set of root files, returns the set of type directive names
1060+
* Given a set of options, returns the set of type directive names
10651061
* that should be included for this program automatically.
10661062
* This list could either come from the config file,
10671063
* or from enumerating the types root + initial secondary types lookup location.
10681064
* More type directives might appear in the program later as a result of loading actual source files;
10691065
* this list is only the set of defaults that are implicitly included.
10701066
*/
1071-
export function getAutomaticTypeDirectiveNames(options: CompilerOptions, rootFiles: string[], host: CompilerHost): string[] {
1067+
export function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[] {
10721068
// Use explicit type list from tsconfig.json
10731069
if (options.types) {
10741070
return options.types;
@@ -1081,7 +1077,10 @@ namespace ts {
10811077
if (typeRoots) {
10821078
for (const root of typeRoots) {
10831079
if (host.directoryExists(root)) {
1084-
result = result.concat(host.getDirectories(root));
1080+
for (const typeDirectivePath of host.getDirectories(root)) {
1081+
// Return just the type directive names
1082+
result = result.concat(getBaseFileName(normalizePath(typeDirectivePath)));
1083+
}
10851084
}
10861085
}
10871086
}
@@ -1156,11 +1155,11 @@ namespace ts {
11561155
forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false));
11571156

11581157
// load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders
1159-
const typeReferences: string[] = getAutomaticTypeDirectiveNames(options, rootNames, host);
1158+
const typeReferences: string[] = getAutomaticTypeDirectiveNames(options, host);
11601159

11611160
if (typeReferences) {
1162-
const inferredRoot = getInferredTypesRoot(options, rootNames, host);
1163-
const containingFilename = combinePaths(inferredRoot, "__inferred type names__.ts");
1161+
// This containingFilename needs to match with the one used in managed-side
1162+
const containingFilename = combinePaths(host.getCurrentDirectory(), "__inferred type names__.ts");
11641163
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename);
11651164
for (let i = 0; i < typeReferences.length; i++) {
11661165
processTypeReferenceDirective(typeReferences[i], resolutions[i]);

src/compiler/types.ts

+11
Original file line numberDiff line numberDiff line change
@@ -1680,6 +1680,16 @@ namespace ts {
16801680
antecedent: FlowNode;
16811681
}
16821682

1683+
export type FlowType = Type | IncompleteType;
1684+
1685+
// Incomplete types occur during control flow analysis of loops. An IncompleteType
1686+
// is distinguished from a regular type by a flags value of zero. Incomplete type
1687+
// objects are internal to the getFlowTypeOfRefecence function and never escape it.
1688+
export interface IncompleteType {
1689+
flags: TypeFlags; // No flags set
1690+
type: Type; // The type marked incomplete
1691+
}
1692+
16831693
export interface AmdDependency {
16841694
path: string;
16851695
name: string;
@@ -2978,6 +2988,7 @@ namespace ts {
29782988
directoryExists?(directoryName: string): boolean;
29792989
realpath?(path: string): string;
29802990
getCurrentDirectory?(): string;
2991+
getDirectories?(path: string): string[];
29812992
}
29822993

29832994
export interface ResolvedModule {

src/compiler/utilities.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -3521,12 +3521,7 @@ namespace ts {
35213521
// export { x, y }
35223522
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
35233523
const name = (specifier.propertyName || specifier.name).text;
3524-
if (!exportSpecifiers[name]) {
3525-
exportSpecifiers[name] = [specifier];
3526-
}
3527-
else {
3528-
exportSpecifiers[name].push(specifier);
3529-
}
3524+
getOrUpdateProperty(exportSpecifiers, name, () => []).push(specifier);
35303525
}
35313526
}
35323527
break;
@@ -3965,6 +3960,7 @@ namespace ts {
39653960
|| kind === SyntaxKind.MethodDeclaration
39663961
|| kind === SyntaxKind.MethodSignature
39673962
|| kind === SyntaxKind.ModuleDeclaration
3963+
|| kind === SyntaxKind.NamespaceExportDeclaration
39683964
|| kind === SyntaxKind.NamespaceImport
39693965
|| kind === SyntaxKind.Parameter
39703966
|| kind === SyntaxKind.PropertyAssignment

src/services/services.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -1891,7 +1891,7 @@ namespace ts {
18911891
};
18921892
}
18931893

1894-
// Cache host information about scrip Should be refreshed
1894+
// Cache host information about script should be refreshed
18951895
// at each language service public entry point, since we don't know when
18961896
// set of scripts handled by the host changes.
18971897
class HostCache {
@@ -4835,7 +4835,14 @@ namespace ts {
48354835
}
48364836
if (symbolFlags & SymbolFlags.Alias) {
48374837
addNewLineIfDisplayPartsExist();
4838-
displayParts.push(keywordPart(SyntaxKind.ImportKeyword));
4838+
if (symbol.declarations[0].kind === SyntaxKind.NamespaceExportDeclaration) {
4839+
displayParts.push(keywordPart(SyntaxKind.ExportKeyword));
4840+
displayParts.push(spacePart());
4841+
displayParts.push(keywordPart(SyntaxKind.NamespaceKeyword));
4842+
}
4843+
else {
4844+
displayParts.push(keywordPart(SyntaxKind.ImportKeyword));
4845+
}
48394846
displayParts.push(spacePart());
48404847
addFullSymbolName(symbol);
48414848
ts.forEach(symbol.declarations, declaration => {

0 commit comments

Comments
 (0)