Skip to content

Commit 3b60fe0

Browse files
committed
Merge branch 'master' into inferToPromiseLikeTypes
2 parents 17517d5 + 6d7539a commit 3b60fe0

File tree

170 files changed

+823
-297
lines changed

Some content is hidden

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

170 files changed

+823
-297
lines changed

src/compiler/checker.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,18 +2388,7 @@ namespace ts {
23882388
));
23892389
}
23902390
else {
2391-
if (moduleSymbol.exports && moduleSymbol.exports.has(node.symbol.escapedName)) {
2392-
error(
2393-
node.name,
2394-
Diagnostics.Module_0_has_no_default_export_Did_you_mean_to_use_import_1_from_0_instead,
2395-
symbolToString(moduleSymbol),
2396-
symbolToString(node.symbol),
2397-
);
2398-
}
2399-
else {
2400-
error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol));
2401-
}
2402-
2391+
reportNonDefaultExport(moduleSymbol, node);
24032392
}
24042393
}
24052394
else if (hasSyntheticDefault) {
@@ -2413,6 +2402,30 @@ namespace ts {
24132402
}
24142403
}
24152404

2405+
function reportNonDefaultExport(moduleSymbol: Symbol, node: ImportClause) {
2406+
if (moduleSymbol.exports?.has(node.symbol.escapedName)) {
2407+
error(
2408+
node.name,
2409+
Diagnostics.Module_0_has_no_default_export_Did_you_mean_to_use_import_1_from_0_instead,
2410+
symbolToString(moduleSymbol),
2411+
symbolToString(node.symbol),
2412+
);
2413+
}
2414+
else {
2415+
const diagnostic = error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol));
2416+
const exportStar = moduleSymbol.exports?.get(InternalSymbolName.ExportStar);
2417+
if (exportStar) {
2418+
const defaultExport = find(exportStar.declarations, decl => !!(
2419+
isExportDeclaration(decl) && decl.moduleSpecifier &&
2420+
resolveExternalModuleName(decl, decl.moduleSpecifier)?.exports?.has(InternalSymbolName.Default)
2421+
));
2422+
if (defaultExport) {
2423+
addRelatedInfo(diagnostic, createDiagnosticForNode(defaultExport, Diagnostics.export_Asterisk_does_not_re_export_a_default));
2424+
}
2425+
}
2426+
}
2427+
}
2428+
24162429
function getTargetOfNamespaceImport(node: NamespaceImport, dontResolveAlias: boolean): Symbol | undefined {
24172430
const moduleSpecifier = node.parent.parent.moduleSpecifier;
24182431
const immediate = resolveExternalModuleName(node, moduleSpecifier);

src/compiler/commandLineParser.ts

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,10 +1242,9 @@ namespace ts {
12421242
}
12431243

12441244
function parseResponseFile(fileName: string) {
1245-
const text = readFile ? readFile(fileName) : sys.readFile(fileName);
1246-
1247-
if (!text) {
1248-
errors.push(createCompilerDiagnostic(Diagnostics.File_0_not_found, fileName));
1245+
const text = tryReadFile(fileName, readFile || (fileName => sys.readFile(fileName)));
1246+
if (!isString(text)) {
1247+
errors.push(text);
12491248
return;
12501249
}
12511250

@@ -1466,18 +1465,9 @@ namespace ts {
14661465
extendedConfigCache?: Map<ExtendedConfigCacheEntry>,
14671466
watchOptionsToExtend?: WatchOptions
14681467
): ParsedCommandLine | undefined {
1469-
let configFileText: string | undefined;
1470-
try {
1471-
configFileText = host.readFile(configFileName);
1472-
}
1473-
catch (e) {
1474-
const error = createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message);
1475-
host.onUnRecoverableConfigFileDiagnostic(error);
1476-
return undefined;
1477-
}
1478-
if (!configFileText) {
1479-
const error = createCompilerDiagnostic(Diagnostics.File_0_not_found, configFileName);
1480-
host.onUnRecoverableConfigFileDiagnostic(error);
1468+
const configFileText = tryReadFile(configFileName, fileName => host.readFile(fileName));
1469+
if (!isString(configFileText)) {
1470+
host.onUnRecoverableConfigFileDiagnostic(configFileText);
14811471
return undefined;
14821472
}
14831473

@@ -1530,15 +1520,16 @@ namespace ts {
15301520
return isString(textOrDiagnostic) ? parseJsonText(fileName, textOrDiagnostic) : <TsConfigSourceFile>{ parseDiagnostics: [textOrDiagnostic] };
15311521
}
15321522

1533-
function tryReadFile(fileName: string, readFile: (path: string) => string | undefined): string | Diagnostic {
1523+
/*@internal*/
1524+
export function tryReadFile(fileName: string, readFile: (path: string) => string | undefined): string | Diagnostic {
15341525
let text: string | undefined;
15351526
try {
15361527
text = readFile(fileName);
15371528
}
15381529
catch (e) {
15391530
return createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message);
15401531
}
1541-
return text === undefined ? createCompilerDiagnostic(Diagnostics.The_specified_path_does_not_exist_Colon_0, fileName) : text;
1532+
return text === undefined ? createCompilerDiagnostic(Diagnostics.Cannot_read_file_0, fileName) : text;
15421533
}
15431534

15441535
function commandLineOptionsToMap(options: readonly CommandLineOption[]) {

src/compiler/diagnosticMessages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,10 @@
611611
"category": "Error",
612612
"code": 1194
613613
},
614+
"'export *' does not re-export a default.": {
615+
"category": "Error",
616+
"code": 1195
617+
},
614618
"Catch clause variable cannot have a type annotation.": {
615619
"category": "Error",
616620
"code": 1196
@@ -3461,6 +3465,10 @@
34613465
"category": "Error",
34623466
"code": 5082
34633467
},
3468+
"Cannot read file '{0}'.": {
3469+
"category": "Error",
3470+
"code": 5083
3471+
},
34643472

34653473
"Generates a sourcemap for each corresponding '.d.ts' file.": {
34663474
"category": "Message",

src/compiler/parser.ts

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7752,7 +7752,6 @@ namespace ts {
77527752
const incrementalSourceFile = <IncrementalNode><Node>sourceFile;
77537753
Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed);
77547754
incrementalSourceFile.hasBeenIncrementallyParsed = true;
7755-
77567755
const oldText = sourceFile.text;
77577756
const syntaxCursor = createSyntaxCursor(sourceFile);
77587757

@@ -7805,10 +7804,68 @@ namespace ts {
78057804
// will immediately bail out of walking any subtrees when we can see that their parents
78067805
// are already correct.
78077806
const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind);
7808-
7807+
result.commentDirectives = getNewCommentDirectives(
7808+
sourceFile.commentDirectives,
7809+
result.commentDirectives,
7810+
changeRange.span.start,
7811+
textSpanEnd(changeRange.span),
7812+
delta,
7813+
oldText,
7814+
newText,
7815+
aggressiveChecks
7816+
);
78097817
return result;
78107818
}
78117819

7820+
function getNewCommentDirectives(
7821+
oldDirectives: CommentDirective[] | undefined,
7822+
newDirectives: CommentDirective[] | undefined,
7823+
changeStart: number,
7824+
changeRangeOldEnd: number,
7825+
delta: number,
7826+
oldText: string,
7827+
newText: string,
7828+
aggressiveChecks: boolean
7829+
): CommentDirective[] | undefined {
7830+
if (!oldDirectives) return newDirectives;
7831+
let commentDirectives: CommentDirective[] | undefined;
7832+
let addedNewlyScannedDirectives = false;
7833+
for (const directive of oldDirectives) {
7834+
const { range, type } = directive;
7835+
// Range before the change
7836+
if (range.end < changeStart) {
7837+
commentDirectives = append(commentDirectives, directive);
7838+
}
7839+
else if (range.pos > changeRangeOldEnd) {
7840+
addNewlyScannedDirectives();
7841+
// Node is entirely past the change range. We need to move both its pos and
7842+
// end, forward or backward appropriately.
7843+
const updatedDirective: CommentDirective = {
7844+
range: { pos: range.pos + delta, end: range.end + delta },
7845+
type
7846+
};
7847+
commentDirectives = append(commentDirectives, updatedDirective);
7848+
if (aggressiveChecks) {
7849+
Debug.assert(oldText.substring(range.pos, range.end) === newText.substring(updatedDirective.range.pos, updatedDirective.range.end));
7850+
}
7851+
}
7852+
// Ignore ranges that fall in change range
7853+
}
7854+
addNewlyScannedDirectives();
7855+
return commentDirectives;
7856+
7857+
function addNewlyScannedDirectives() {
7858+
if (addedNewlyScannedDirectives) return;
7859+
addedNewlyScannedDirectives = true;
7860+
if (!commentDirectives) {
7861+
commentDirectives = newDirectives;
7862+
}
7863+
else if (newDirectives) {
7864+
commentDirectives.push(...newDirectives);
7865+
}
7866+
}
7867+
}
7868+
78127869
function moveElementEntirelyPastChangeRange(element: IncrementalElement, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) {
78137870
if (isArray) {
78147871
visitArray(<IncrementalNodeArray>element);

src/harness/harnessIO.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,12 +847,28 @@ namespace Harness {
847847
result.maps.forEach(sourceMap => {
848848
if (sourceMapCode) sourceMapCode += "\r\n";
849849
sourceMapCode += fileOutput(sourceMap, harnessSettings);
850+
if (!options.inlineSourceMap) {
851+
sourceMapCode += createSourceMapPreviewLink(sourceMap.text, result);
852+
}
850853
});
851854
}
852855
Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ".js.map"), sourceMapCode);
853856
}
854857
}
855858

859+
function createSourceMapPreviewLink(sourcemap: string, result: compiler.CompilationResult) {
860+
const sourcemapJSON = JSON.parse(sourcemap);
861+
const outputJSFile = result.outputs.find(td => td.file.endsWith(sourcemapJSON.file));
862+
if (!outputJSFile) return "";
863+
864+
const sourceTDs = ts.map(sourcemapJSON.sources, (s: string) => result.inputs.find(td => td.file.endsWith(s)));
865+
const anyUnfoundSources = ts.contains(sourceTDs, /*value*/ undefined);
866+
if (anyUnfoundSources) return "";
867+
868+
const hash = "#base64," + ts.map([outputJSFile.text, sourcemap].concat(sourceTDs.map(td => td!.text)), (s) => ts.convertToBase64(decodeURIComponent(encodeURIComponent(s)))).join(",");
869+
return "\n//// https://sokra.github.io/source-map-visualization" + hash + "\n";
870+
}
871+
856872
export function doJsEmitBaseline(baselinePath: string, header: string, options: ts.CompilerOptions, result: compiler.CompilationResult, tsConfigFiles: readonly TestFile[], toBeCompiled: readonly TestFile[], otherFiles: readonly TestFile[], harnessSettings: TestCaseParser.CompilerSettings) {
857873
if (!options.noEmit && !options.emitDeclarationOnly && result.js.size === 0 && result.diagnostics.length === 0) {
858874
throw new Error("Expected at least one js file to be emitted or at least one error to be created.");

src/lib/es2015.core.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,27 +213,27 @@ interface NumberConstructor {
213213
* number. Only finite values of the type number, result in true.
214214
* @param number A numeric value.
215215
*/
216-
isFinite(number: number): boolean;
216+
isFinite(number: unknown): boolean;
217217

218218
/**
219219
* Returns true if the value passed is an integer, false otherwise.
220220
* @param number A numeric value.
221221
*/
222-
isInteger(number: number): boolean;
222+
isInteger(number: unknown): boolean;
223223

224224
/**
225225
* Returns a Boolean value that indicates whether a value is the reserved value NaN (not a
226226
* number). Unlike the global isNaN(), Number.isNaN() doesn't forcefully convert the parameter
227227
* to a number. Only values of the type number, that are also NaN, result in true.
228228
* @param number A numeric value.
229229
*/
230-
isNaN(number: number): boolean;
230+
isNaN(number: unknown): boolean;
231231

232232
/**
233233
* Returns true if the value passed is a safe integer.
234234
* @param number A numeric value.
235235
*/
236-
isSafeInteger(number: number): boolean;
236+
isSafeInteger(number: unknown): boolean;
237237

238238
/**
239239
* The value of the largest integer n such that n and n + 1 are both exactly representable as

src/lib/es2015.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/// <reference lib="es5" />
22
/// <reference lib="es2015.core" />
33
/// <reference lib="es2015.collection" />
4+
/// <reference lib="es2015.iterable" />
45
/// <reference lib="es2015.generator" />
56
/// <reference lib="es2015.promise" />
6-
/// <reference lib="es2015.iterable" />
77
/// <reference lib="es2015.proxy" />
88
/// <reference lib="es2015.reflect" />
99
/// <reference lib="es2015.symbol" />

src/lib/es2018.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/// <reference lib="es2017" />
2-
/// <reference lib="es2018.asyncgenerator" />
32
/// <reference lib="es2018.asynciterable" />
3+
/// <reference lib="es2018.asyncgenerator" />
44
/// <reference lib="es2018.promise" />
55
/// <reference lib="es2018.regexp" />
66
/// <reference lib="es2018.intl" />

src/server/editorServices.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,13 +1974,13 @@ namespace ts.server {
19741974
// Read updated contents from disk
19751975
const configFilename = normalizePath(project.getConfigFilePath());
19761976

1977-
const configFileContent = this.host.readFile(configFilename) || "";
1978-
1979-
const result = parseJsonText(configFilename, configFileContent);
1977+
const configFileContent = tryReadFile(configFilename, fileName => this.host.readFile(fileName));
1978+
const result = parseJsonText(configFilename, isString(configFileContent) ? configFileContent : "");
19801979
if (!result.endOfFileToken) {
19811980
result.endOfFileToken = <EndOfFileToken>{ kind: SyntaxKind.EndOfFileToken };
19821981
}
19831982
const configFileErrors = result.parseDiagnostics as Diagnostic[];
1983+
if (!isString(configFileContent)) configFileErrors.push(configFileContent);
19841984
const parsedCommandLine = parseJsonSourceFileConfigFileContent(
19851985
result,
19861986
project.getCachedDirectoryStructureHost(),

src/services/completions.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,6 +1271,7 @@ namespace ts.Completions {
12711271
function tryGetGlobalSymbols(): boolean {
12721272
const result: GlobalsSearch = tryGetObjectLikeCompletionSymbols()
12731273
|| tryGetImportOrExportClauseCompletionSymbols()
1274+
|| tryGetLocalNamedExportCompletionSymbols()
12741275
|| tryGetConstructorCompletion()
12751276
|| tryGetClassLikeCompletionSymbols()
12761277
|| tryGetJsxCompletionSymbols()
@@ -1881,19 +1882,17 @@ namespace ts.Completions {
18811882
* export { | };
18821883
*
18831884
* Relevant symbols are stored in the captured 'symbols' variable.
1884-
*
1885-
* @returns true if 'symbols' was successfully populated; false otherwise.
18861885
*/
18871886
function tryGetImportOrExportClauseCompletionSymbols(): GlobalsSearch {
18881887
// `import { |` or `import { a as 0, | }`
18891888
const namedImportsOrExports = contextToken && (contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken)
18901889
? tryCast(contextToken.parent, isNamedImportsOrExports) : undefined;
18911890
if (!namedImportsOrExports) return GlobalsSearch.Continue;
18921891

1893-
// cursor is in an import clause
1894-
// try to show exported member for imported module
1892+
// try to show exported member for imported/re-exported module
18951893
const { moduleSpecifier } = namedImportsOrExports.kind === SyntaxKind.NamedImports ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent;
1896-
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier!); // TODO: GH#18217
1894+
if (!moduleSpecifier) return namedImportsOrExports.kind === SyntaxKind.NamedImports ? GlobalsSearch.Fail : GlobalsSearch.Continue;
1895+
const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier); // TODO: GH#18217
18971896
if (!moduleSpecifierSymbol) return GlobalsSearch.Fail;
18981897

18991898
completionKind = CompletionKind.MemberLike;
@@ -1904,6 +1903,36 @@ namespace ts.Completions {
19041903
return GlobalsSearch.Success;
19051904
}
19061905

1906+
/**
1907+
* Adds local declarations for completions in named exports:
1908+
*
1909+
* export { | };
1910+
*
1911+
* Does not check for the absence of a module specifier (`export {} from "./other"`)
1912+
* because `tryGetImportOrExportClauseCompletionSymbols` runs first and handles that,
1913+
* preventing this function from running.
1914+
*/
1915+
function tryGetLocalNamedExportCompletionSymbols(): GlobalsSearch {
1916+
const namedExports = contextToken && (contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken)
1917+
? tryCast(contextToken.parent, isNamedExports)
1918+
: undefined;
1919+
1920+
if (!namedExports) {
1921+
return GlobalsSearch.Continue;
1922+
}
1923+
1924+
const localsContainer = findAncestor(namedExports, or(isSourceFile, isModuleDeclaration))!;
1925+
completionKind = CompletionKind.None;
1926+
isNewIdentifierLocation = false;
1927+
localsContainer.locals?.forEach((symbol, name) => {
1928+
symbols.push(symbol);
1929+
if (localsContainer.symbol?.exports?.has(name)) {
1930+
symbolToSortTextMap[getSymbolId(symbol)] = SortText.OptionalMember;
1931+
}
1932+
});
1933+
return GlobalsSearch.Success;
1934+
}
1935+
19071936
/**
19081937
* Aggregates relevant symbols for completion in class declaration
19091938
* Relevant symbols are stored in the captured 'symbols' variable.
@@ -2299,7 +2328,7 @@ namespace ts.Completions {
22992328
}
23002329
}
23012330

2302-
// Set SortText to OptionalMember if it is an optinoal member
2331+
// Set SortText to OptionalMember if it is an optional member
23032332
function setSortTextToOptionalMember() {
23042333
symbols.forEach(m => {
23052334
if (m.flags & SymbolFlags.Optional) {

0 commit comments

Comments
 (0)