Skip to content

Commit 0a8b72d

Browse files
Merge remote-tracking branch 'remotes/origin/master' into microsoftGH-23226
2 parents 0af12d9 + 4170f35 commit 0a8b72d

File tree

142 files changed

+6164
-7656
lines changed

Some content is hidden

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

142 files changed

+6164
-7656
lines changed

src/compiler/checker.ts

+60-18
Original file line numberDiff line numberDiff line change
@@ -2216,7 +2216,22 @@ namespace ts {
22162216
// An external module with an 'export =' declaration resolves to the target of the 'export =' declaration,
22172217
// and an external module with no 'export =' declaration resolves to the module itself.
22182218
function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol {
2219-
return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias)) || moduleSymbol;
2219+
return moduleSymbol && getMergedSymbol(resolveSymbol(getCommonJsExportEquals(moduleSymbol), dontResolveAlias)) || moduleSymbol;
2220+
}
2221+
2222+
function getCommonJsExportEquals(moduleSymbol: Symbol): Symbol {
2223+
const exported = moduleSymbol.exports.get(InternalSymbolName.ExportEquals);
2224+
if (!exported || !exported.exports || moduleSymbol.exports.size === 1) {
2225+
return exported;
2226+
}
2227+
const merged = cloneSymbol(exported);
2228+
moduleSymbol.exports.forEach((s, name) => {
2229+
if (name === InternalSymbolName.ExportEquals) return;
2230+
if (!merged.exports.has(name)) {
2231+
merged.exports.set(name, s);
2232+
}
2233+
});
2234+
return merged;
22202235
}
22212236

22222237
// An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export ='
@@ -4350,7 +4365,8 @@ namespace ts {
43504365
return unknownType;
43514366
}
43524367

4353-
if (isPropertyAccessExpression(expression.left) && expression.left.expression.kind === SyntaxKind.ThisKeyword) {
4368+
const special = getSpecialPropertyAssignmentKind(expression);
4369+
if (special === SpecialPropertyAssignmentKind.ThisProperty) {
43544370
const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false);
43554371
// Properties defined in a constructor (or javascript constructor function) don't get undefined added.
43564372
// Function expressions that are assigned to the prototype count as methods.
@@ -4380,7 +4396,33 @@ namespace ts {
43804396
}
43814397
else if (!jsDocType) {
43824398
// If we don't have an explicit JSDoc type, get the type from the expression.
4383-
const type = getWidenedLiteralType(checkExpressionCached(expression.right));
4399+
let type = getWidenedLiteralType(checkExpressionCached(expression.right));
4400+
4401+
if (getObjectFlags(type) & ObjectFlags.Anonymous &&
4402+
special === SpecialPropertyAssignmentKind.ModuleExports &&
4403+
symbol.escapedName === InternalSymbolName.ExportEquals) {
4404+
const exportedType = resolveStructuredTypeMembers(type as AnonymousType);
4405+
const members = createSymbolTable();
4406+
copyEntries(exportedType.members, members);
4407+
symbol.exports.forEach((s, name) => {
4408+
if (members.has(name)) {
4409+
const exportedMember = exportedType.members.get(name);
4410+
const union = createSymbol(s.flags | exportedMember.flags, name);
4411+
union.type = getUnionType([getTypeOfSymbol(s), getTypeOfSymbol(exportedMember)]);
4412+
members.set(name, union);
4413+
}
4414+
else {
4415+
members.set(name, s);
4416+
}
4417+
});
4418+
type = createAnonymousType(
4419+
exportedType.symbol,
4420+
members,
4421+
exportedType.callSignatures,
4422+
exportedType.constructSignatures,
4423+
exportedType.stringIndexInfo,
4424+
exportedType.numberIndexInfo);
4425+
}
43844426
let anyedType = type;
43854427
if (isEmptyArrayLiteralType(type)) {
43864428
anyedType = anyArrayType;
@@ -7158,15 +7200,15 @@ namespace ts {
71587200
return symbol.members.get(InternalSymbolName.Index);
71597201
}
71607202

7161-
function getIndexDeclarationOfSymbol(symbol: Symbol, kind: IndexKind): SignatureDeclaration {
7203+
function getIndexDeclarationOfSymbol(symbol: Symbol, kind: IndexKind): IndexSignatureDeclaration {
71627204
const syntaxKind = kind === IndexKind.Number ? SyntaxKind.NumberKeyword : SyntaxKind.StringKeyword;
71637205
const indexSymbol = getIndexSymbol(symbol);
71647206
if (indexSymbol) {
71657207
for (const decl of indexSymbol.declarations) {
7166-
const node = <SignatureDeclaration>decl;
7208+
const node = cast(decl, isIndexSignatureDeclaration);
71677209
if (node.parameters.length === 1) {
71687210
const parameter = node.parameters[0];
7169-
if (parameter && parameter.type && parameter.type.kind === syntaxKind) {
7211+
if (parameter.type && parameter.type.kind === syntaxKind) {
71707212
return node;
71717213
}
71727214
}
@@ -7176,7 +7218,7 @@ namespace ts {
71767218
return undefined;
71777219
}
71787220

7179-
function createIndexInfo(type: Type, isReadonly: boolean, declaration?: SignatureDeclaration): IndexInfo {
7221+
function createIndexInfo(type: Type, isReadonly: boolean, declaration?: IndexSignatureDeclaration): IndexInfo {
71807222
return { type, isReadonly, declaration };
71817223
}
71827224

@@ -16624,12 +16666,18 @@ namespace ts {
1662416666
}
1662516667
}
1662616668
}
16627-
const suggestion = getSuggestionForNonexistentProperty(propNode, containingType);
16628-
if (suggestion !== undefined) {
16629-
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestion);
16669+
const promisedType = getPromisedTypeOfPromise(containingType);
16670+
if (promisedType && getPropertyOfType(promisedType, propNode.escapedText)) {
16671+
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_forget_to_use_await, declarationNameToString(propNode), typeToString(containingType));
1663016672
}
1663116673
else {
16632-
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
16674+
const suggestion = getSuggestionForNonexistentProperty(propNode, containingType);
16675+
if (suggestion !== undefined) {
16676+
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestion);
16677+
}
16678+
else {
16679+
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
16680+
}
1663316681
}
1663416682
diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo));
1663516683
}
@@ -24576,7 +24624,7 @@ namespace ts {
2457624624
const exportEqualsSymbol = moduleSymbol.exports.get("export=" as __String);
2457724625
if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) {
2457824626
const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration;
24579-
if (!isTopLevelInExternalModuleAugmentation(declaration)) {
24627+
if (!isTopLevelInExternalModuleAugmentation(declaration) && !isInJavaScriptFile(declaration)) {
2458024628
error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
2458124629
}
2458224630
}
@@ -24657,7 +24705,6 @@ namespace ts {
2465724705
case SyntaxKind.ConstructorType:
2465824706
case SyntaxKind.CallSignature:
2465924707
case SyntaxKind.ConstructSignature:
24660-
return checkSignatureDeclaration(<SignatureDeclaration>node);
2466124708
case SyntaxKind.IndexSignature:
2466224709
return checkSignatureDeclaration(<SignatureDeclaration>node);
2466324710
case SyntaxKind.MethodDeclaration:
@@ -24777,8 +24824,6 @@ namespace ts {
2477724824
case SyntaxKind.ExportAssignment:
2477824825
return checkExportAssignment(<ExportAssignment>node);
2477924826
case SyntaxKind.EmptyStatement:
24780-
checkGrammarStatementInAmbientContext(node);
24781-
return;
2478224827
case SyntaxKind.DebuggerStatement:
2478324828
checkGrammarStatementInAmbientContext(node);
2478424829
return;
@@ -25456,9 +25501,6 @@ namespace ts {
2545625501
}
2545725502

2545825503
function getShorthandAssignmentValueSymbol(location: Node): Symbol {
25459-
// The function returns a value symbol of an identifier in the short-hand property assignment.
25460-
// This is necessary as an identifier in short-hand property assignment can contains two meaning:
25461-
// property name and property value.
2546225504
if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) {
2546325505
return resolveEntityName((<ShorthandPropertyAssignment>location).name, SymbolFlags.Value | SymbolFlags.Alias);
2546425506
}

src/compiler/core.ts

+2
Original file line numberDiff line numberDiff line change
@@ -2246,6 +2246,8 @@ namespace ts {
22462246
* Adds a trailing directory separator to a path, if it does not already have one.
22472247
* @param path The path.
22482248
*/
2249+
export function ensureTrailingDirectorySeparator(path: Path): Path;
2250+
export function ensureTrailingDirectorySeparator(path: string): string;
22492251
export function ensureTrailingDirectorySeparator(path: string) {
22502252
if (path.charAt(path.length - 1) !== directorySeparator) {
22512253
return path + directorySeparator;

src/compiler/diagnosticMessages.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -2012,7 +2012,10 @@
20122012
"category": "Error",
20132013
"code": 2569
20142014
},
2015-
2015+
"Property '{0}' does not exist on type '{1}'. Did you forget to use 'await'?": {
2016+
"category": "Error",
2017+
"code": 2570
2018+
},
20162019
"JSX element attributes type '{0}' may not be a union type.": {
20172020
"category": "Error",
20182021
"code": 2600

src/compiler/moduleNameResolver.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ namespace ts {
117117
}
118118
}
119119

120-
function readJson(path: string, host: ModuleResolutionHost): PackageJson {
120+
/* @internal */
121+
export function readJson(path: string, host: { readFile(fileName: string): string | undefined }): object {
121122
try {
122123
const jsonText = host.readFile(path);
123124
return jsonText ? JSON.parse(jsonText) : {};
@@ -300,7 +301,7 @@ namespace ts {
300301
// `types-publisher` sometimes creates packages with `"typings": null` for packages that don't provide their own types.
301302
// See `createNotNeededPackageJSON` in the types-publisher` repo.
302303
// tslint:disable-next-line:no-null-keyword
303-
const isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null;
304+
const isNotNeededPackage = host.fileExists(packageJsonPath) && (readJson(packageJsonPath, host) as PackageJson).typings === null;
304305
if (!isNotNeededPackage) {
305306
// Return just the type directive names
306307
result.push(getBaseFileName(normalized));
@@ -983,7 +984,7 @@ namespace ts {
983984
const directoryExists = !onlyRecordFailures && directoryProbablyExists(nodeModuleDirectory, host);
984985
const packageJsonPath = pathToPackageJson(nodeModuleDirectory);
985986
if (directoryExists && host.fileExists(packageJsonPath)) {
986-
const packageJsonContent = readJson(packageJsonPath, host);
987+
const packageJsonContent = readJson(packageJsonPath, host) as PackageJson;
987988
if (subModuleName === "") { // looking up the root - need to handle types/typings/main redirects for subModuleName
988989
const path = tryReadPackageJsonFields(/*readTypes*/ true, packageJsonContent, nodeModuleDirectory, state);
989990
if (typeof path === "string") {
@@ -1034,7 +1035,7 @@ namespace ts {
10341035
const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(file), state.host);
10351036
const fromFile = tryFile(file, failedLookupLocations, onlyRecordFailures, state);
10361037
if (fromFile) {
1037-
const resolved = fromFile && resolvedIfExtensionMatches(extensions, fromFile);
1038+
const resolved = resolvedIfExtensionMatches(extensions, fromFile);
10381039
if (resolved) {
10391040
return resolved;
10401041
}

src/compiler/types.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -2839,6 +2839,10 @@ namespace ts {
28392839
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
28402840
getSymbolAtLocation(node: Node): Symbol | undefined;
28412841
getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[];
2842+
/**
2843+
* The function returns the value (local variable) symbol of an identifier in the short-hand property assignment.
2844+
* This is necessary as an identifier in short-hand property assignment can contains two meaning: property name and property value.
2845+
*/
28422846
getShorthandAssignmentValueSymbol(location: Node): Symbol | undefined;
28432847
getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol | undefined;
28442848
/**
@@ -3968,7 +3972,7 @@ namespace ts {
39683972
export interface IndexInfo {
39693973
type: Type;
39703974
isReadonly: boolean;
3971-
declaration?: SignatureDeclaration;
3975+
declaration?: IndexSignatureDeclaration;
39723976
}
39733977

39743978
/* @internal */

src/harness/unittests/typingsInstaller.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,15 @@ namespace ts.projectSystem {
141141
checkNumberOfProjects(projectService, { configuredProjects: 1 });
142142
const p = configuredProjectAt(projectService, 0);
143143
checkProjectActualFiles(p, [file1.path, tsconfig.path]);
144+
checkWatchedFiles(host, [tsconfig.path, libFile.path, packageJson.path, "/a/b/bower_components", "/a/b/node_modules"]);
144145

145146
installer.installAll(/*expectedCount*/ 1);
146147

147148
checkNumberOfProjects(projectService, { configuredProjects: 1 });
148149
host.checkTimeoutQueueLengthAndRun(2);
149150
checkProjectActualFiles(p, [file1.path, jquery.path, tsconfig.path]);
151+
// should not watch jquery
152+
checkWatchedFiles(host, [tsconfig.path, libFile.path, packageJson.path, "/a/b/bower_components", "/a/b/node_modules"]);
150153
});
151154

152155
it("inferred project (typings installed)", () => {
@@ -188,7 +191,7 @@ namespace ts.projectSystem {
188191
checkProjectActualFiles(p, [file1.path]);
189192

190193
installer.installAll(/*expectedCount*/ 1);
191-
194+
host.checkTimeoutQueueLengthAndRun(2);
192195
checkNumberOfProjects(projectService, { inferredProjects: 1 });
193196
checkProjectActualFiles(p, [file1.path, jquery.path]);
194197
});
@@ -961,6 +964,7 @@ namespace ts.projectSystem {
961964
assert.isTrue(host.fileExists(node.path), "typings for 'node' should be created");
962965
assert.isTrue(host.fileExists(commander.path), "typings for 'commander' should be created");
963966

967+
host.checkTimeoutQueueLengthAndRun(2);
964968
checkProjectActualFiles(service.inferredProjects[0], [file.path, node.path, commander.path]);
965969
});
966970

@@ -1106,7 +1110,7 @@ namespace ts.projectSystem {
11061110
checkProjectActualFiles(p, [file1.path]);
11071111

11081112
installer.installAll(/*expectedCount*/ 1);
1109-
1113+
host.checkTimeoutQueueLengthAndRun(2);
11101114
checkNumberOfProjects(projectService, { inferredProjects: 1 });
11111115
checkProjectActualFiles(p, [file1.path, jquery.path]);
11121116
});

src/lib/es5.d.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -772,8 +772,7 @@ interface Date {
772772

773773
interface DateConstructor {
774774
new(): Date;
775-
new(value: number): Date;
776-
new(value: string): Date;
775+
new(value: number | string): Date;
777776
new(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date;
778777
(): string;
779778
readonly prototype: Date;

src/server/editorServices.ts

+11-5
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ namespace ts.server {
392392
public readonly useSingleInferredProject: boolean;
393393
public readonly useInferredProjectPerProjectRoot: boolean;
394394
public readonly typingsInstaller: ITypingsInstaller;
395+
private readonly globalCacheLocationDirectoryPath: Path;
395396
public readonly throttleWaitMilliseconds?: number;
396397
private readonly eventHandler?: ProjectServiceEventHandler;
397398
private readonly suppressDiagnosticEvents?: boolean;
@@ -431,6 +432,8 @@ namespace ts.server {
431432
}
432433
this.currentDirectory = this.host.getCurrentDirectory();
433434
this.toCanonicalFileName = createGetCanonicalFileName(this.host.useCaseSensitiveFileNames);
435+
this.globalCacheLocationDirectoryPath = this.typingsInstaller.globalTypingsCacheLocation &&
436+
ensureTrailingDirectorySeparator(this.toPath(this.typingsInstaller.globalTypingsCacheLocation));
434437
this.throttledOperations = new ThrottledOperations(this.host, this.logger);
435438

436439
if (this.typesMapLocation) {
@@ -548,10 +551,11 @@ namespace ts.server {
548551
else {
549552
if (this.pendingEnsureProjectForOpenFiles) {
550553
this.ensureProjectForOpenFiles();
554+
555+
// Send the event to notify that there were background project updates
556+
// send current list of open files
557+
this.sendProjectsUpdatedInBackgroundEvent();
551558
}
552-
// Send the event to notify that there were background project updates
553-
// send current list of open files
554-
this.sendProjectsUpdatedInBackgroundEvent();
555559
}
556560
});
557561
}
@@ -642,7 +646,6 @@ namespace ts.server {
642646
return undefined;
643647
}
644648
if (isInferredProjectName(projectName)) {
645-
this.ensureProjectStructuresUptoDate();
646649
return findProjectByName(projectName, this.inferredProjects);
647650
}
648651
return this.findExternalProjectByProjectName(projectName) || this.findConfiguredProjectByProjectName(toNormalizedPath(projectName));
@@ -1738,7 +1741,10 @@ namespace ts.server {
17381741
private watchClosedScriptInfo(info: ScriptInfo) {
17391742
Debug.assert(!info.fileWatcher);
17401743
// do not watch files with mixed content - server doesn't know how to interpret it
1741-
if (!info.isDynamicOrHasMixedContent()) {
1744+
// do not watch files in the global cache location
1745+
if (!info.isDynamicOrHasMixedContent() &&
1746+
(!this.globalCacheLocationDirectoryPath ||
1747+
!startsWith(info.path, this.globalCacheLocationDirectoryPath))) {
17421748
const { fileName } = info;
17431749
info.fileWatcher = this.watchFactory.watchFilePath(
17441750
this.host,

src/server/server.ts

-6
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,6 @@ namespace ts.server {
211211
}
212212
}
213213

214-
// E.g. "12:34:56.789"
215-
function nowString() {
216-
const d = new Date();
217-
return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}.${d.getMilliseconds()}`;
218-
}
219-
220214
interface QueuedOperation {
221215
operationId: string;
222216
operation: () => void;

0 commit comments

Comments
 (0)