Skip to content

Commit 4dc9423

Browse files
author
Andy Hanson
committed
Merge branch 'master' into unused_suggestion
2 parents ba9cc5b + e0ca8a5 commit 4dc9423

File tree

295 files changed

+7028
-3817
lines changed

Some content is hidden

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

295 files changed

+7028
-3817
lines changed

package-lock.json

+486-692
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/compiler/binder.ts

+82-54
Large diffs are not rendered by default.

src/compiler/checker.ts

+161-120
Large diffs are not rendered by default.

src/compiler/core.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -920,8 +920,7 @@ namespace ts {
920920
export function sum<T extends Record<K, number>, K extends string>(array: ReadonlyArray<T>, prop: K): number {
921921
let result = 0;
922922
for (const v of array) {
923-
// TODO: Remove the following type assertion once the fix for #17069 is merged
924-
result += v[prop] as number;
923+
result += v[prop];
925924
}
926925
return result;
927926
}

src/compiler/factory.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,23 @@ namespace ts {
7070

7171
// Literals
7272

73+
/* @internal */ export function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier, isSingleQuote: boolean): StringLiteral; // tslint:disable-line unified-signatures
7374
/** If a node is passed, creates a string literal whose source text is read from a source node during emit. */
7475
export function createLiteral(value: string | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): StringLiteral;
7576
export function createLiteral(value: number): NumericLiteral;
7677
export function createLiteral(value: boolean): BooleanLiteral;
7778
export function createLiteral(value: string | number | boolean): PrimaryExpression;
78-
export function createLiteral(value: string | number | boolean | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier): PrimaryExpression {
79+
export function createLiteral(value: string | number | boolean | StringLiteral | NoSubstitutionTemplateLiteral | NumericLiteral | Identifier, isSingleQuote?: boolean): PrimaryExpression {
7980
if (typeof value === "number") {
8081
return createNumericLiteral(value + "");
8182
}
8283
if (typeof value === "boolean") {
8384
return value ? createTrue() : createFalse();
8485
}
8586
if (isString(value)) {
86-
return createStringLiteral(value);
87+
const res = createStringLiteral(value);
88+
if (isSingleQuote) res.singleQuote = true;
89+
return res;
8790
}
8891
return createLiteralFromNode(value);
8992
}
@@ -1984,7 +1987,7 @@ namespace ts {
19841987
decorators: ReadonlyArray<Decorator> | undefined,
19851988
modifiers: ReadonlyArray<Modifier> | undefined,
19861989
importClause: ImportClause | undefined,
1987-
moduleSpecifier?: Expression): ImportDeclaration {
1990+
moduleSpecifier: Expression): ImportDeclaration {
19881991
const node = <ImportDeclaration>createSynthesizedNode(SyntaxKind.ImportDeclaration);
19891992
node.decorators = asNodeArray(decorators);
19901993
node.modifiers = asNodeArray(modifiers);

src/compiler/parser.ts

+39-37
Original file line numberDiff line numberDiff line change
@@ -2203,9 +2203,21 @@ namespace ts {
22032203
return finishNode(node);
22042204
}
22052205

2206-
function parseJSDocAllType(): JSDocAllType {
2207-
const result = <JSDocAllType>createNode(SyntaxKind.JSDocAllType);
2206+
function parseJSDocAllType(postFixEquals: boolean): JSDocAllType | JSDocOptionalType {
2207+
const result = createNode(SyntaxKind.JSDocAllType) as JSDocAllType;
2208+
if (postFixEquals) {
2209+
return createJSDocPostfixType(SyntaxKind.JSDocOptionalType, result) as JSDocOptionalType;
2210+
}
2211+
else {
2212+
nextToken();
2213+
}
2214+
return finishNode(result);
2215+
}
2216+
2217+
function parseJSDocNonNullableType(): TypeNode {
2218+
const result = createNode(SyntaxKind.JSDocNonNullableType) as JSDocNonNullableType;
22082219
nextToken();
2220+
result.type = parseNonArrayType();
22092221
return finishNode(result);
22102222
}
22112223

@@ -2259,15 +2271,22 @@ namespace ts {
22592271
parameter.name = parseIdentifierName();
22602272
parseExpected(SyntaxKind.ColonToken);
22612273
}
2262-
parameter.type = parseType();
2274+
parameter.type = parseJSDocType();
22632275
return finishNode(parameter);
22642276
}
22652277

2266-
function parseJSDocNodeWithType(kind: SyntaxKind.JSDocVariadicType | SyntaxKind.JSDocNonNullableType): TypeNode {
2267-
const result = createNode(kind) as JSDocVariadicType | JSDocNonNullableType;
2268-
nextToken();
2269-
result.type = parseNonArrayType();
2270-
return finishNode(result);
2278+
function parseJSDocType() {
2279+
const dotdotdot = parseOptionalToken(SyntaxKind.DotDotDotToken);
2280+
let type = parseType();
2281+
if (dotdotdot) {
2282+
const variadic = createNode(SyntaxKind.JSDocVariadicType, dotdotdot.pos) as JSDocVariadicType;
2283+
variadic.type = type;
2284+
type = finishNode(variadic);
2285+
}
2286+
if (token() === SyntaxKind.EqualsToken) {
2287+
return createJSDocPostfixType(SyntaxKind.JSDocOptionalType, type);
2288+
}
2289+
return type;
22712290
}
22722291

22732292
function parseTypeQuery(): TypeQueryNode {
@@ -2726,13 +2745,15 @@ namespace ts {
27262745
// If these are followed by a dot, then parse these out as a dotted type reference instead.
27272746
return tryParse(parseKeywordAndNoDot) || parseTypeReference();
27282747
case SyntaxKind.AsteriskToken:
2729-
return parseJSDocAllType();
2748+
return parseJSDocAllType(/*postfixEquals*/ false);
2749+
case SyntaxKind.AsteriskEqualsToken:
2750+
return parseJSDocAllType(/*postfixEquals*/ true);
27302751
case SyntaxKind.QuestionToken:
27312752
return parseJSDocUnknownOrNullableType();
27322753
case SyntaxKind.FunctionKeyword:
27332754
return parseJSDocFunctionType();
27342755
case SyntaxKind.ExclamationToken:
2735-
return parseJSDocNodeWithType(SyntaxKind.JSDocNonNullableType);
2756+
return parseJSDocNonNullableType();
27362757
case SyntaxKind.NoSubstitutionTemplateLiteral:
27372758
case SyntaxKind.StringLiteral:
27382759
case SyntaxKind.NumericLiteral:
@@ -2817,13 +2838,6 @@ namespace ts {
28172838
let type = parseNonArrayType();
28182839
while (!scanner.hasPrecedingLineBreak()) {
28192840
switch (token()) {
2820-
case SyntaxKind.EqualsToken:
2821-
// only parse postfix = inside jsdoc, because it's ambiguous elsewhere
2822-
if (!(contextFlags & NodeFlags.JSDoc)) {
2823-
return type;
2824-
}
2825-
type = createJSDocPostfixType(SyntaxKind.JSDocOptionalType, type);
2826-
break;
28272841
case SyntaxKind.ExclamationToken:
28282842
type = createJSDocPostfixType(SyntaxKind.JSDocNonNullableType, type);
28292843
break;
@@ -2889,12 +2903,6 @@ namespace ts {
28892903
return parseTypeOperator(operator);
28902904
case SyntaxKind.InferKeyword:
28912905
return parseInferType();
2892-
case SyntaxKind.DotDotDotToken: {
2893-
const result = createNode(SyntaxKind.JSDocVariadicType) as JSDocVariadicType;
2894-
nextToken();
2895-
result.type = parsePostfixTypeOrHigher();
2896-
return finishNode(result);
2897-
}
28982906
}
28992907
return parsePostfixTypeOrHigher();
29002908
}
@@ -6156,7 +6164,7 @@ namespace ts {
61566164
const result = <JSDocTypeExpression>createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos());
61576165

61586166
const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(SyntaxKind.OpenBraceToken);
6159-
result.type = doInsideOfContext(NodeFlags.JSDoc, parseType);
6167+
result.type = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType);
61606168
if (!mayOmitBraces || hasBrace) {
61616169
parseExpected(SyntaxKind.CloseBraceToken);
61626170
}
@@ -6495,6 +6503,10 @@ namespace ts {
64956503
}
64966504

64976505
function parseBracketNameInPropertyAndParamTag(): { name: EntityName, isBracketed: boolean } {
6506+
if (token() === SyntaxKind.NoSubstitutionTemplateLiteral) {
6507+
// a markdown-quoted name: `arg` is not legal jsdoc, but occurs in the wild
6508+
return { name: createIdentifier(/*isIdentifier*/ true), isBracketed: false };
6509+
}
64986510
// Looking for something like '[foo]', 'foo', '[foo.bar]' or 'foo.bar'
64996511
const isBracketed = parseOptional(SyntaxKind.OpenBracketToken);
65006512
const name = parseJSDocEntityName();
@@ -7231,17 +7243,17 @@ namespace ts {
72317243
forEachChild(sourceFile, visit);
72327244

72337245
if (lastNodeEntirelyBeforePosition) {
7234-
const lastChildOfLastEntireNodeBeforePosition = getLastChild(lastNodeEntirelyBeforePosition);
7246+
const lastChildOfLastEntireNodeBeforePosition = getLastDescendant(lastNodeEntirelyBeforePosition);
72357247
if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) {
72367248
bestResult = lastChildOfLastEntireNodeBeforePosition;
72377249
}
72387250
}
72397251

72407252
return bestResult;
72417253

7242-
function getLastChild(node: Node): Node {
7254+
function getLastDescendant(node: Node): Node {
72437255
while (true) {
7244-
const lastChild = getLastChildWorker(node);
7256+
const lastChild = getLastChild(node);
72457257
if (lastChild) {
72467258
node = lastChild;
72477259
}
@@ -7251,16 +7263,6 @@ namespace ts {
72517263
}
72527264
}
72537265

7254-
function getLastChildWorker(node: Node): Node | undefined {
7255-
let last: Node;
7256-
forEachChild(node, child => {
7257-
if (nodeIsPresent(child)) {
7258-
last = child;
7259-
}
7260-
});
7261-
return last;
7262-
}
7263-
72647266
function visit(child: Node) {
72657267
if (nodeIsMissing(child)) {
72667268
// Missing nodes are effectively invisible to us. We never even consider them

src/compiler/program.ts

+44-55
Original file line numberDiff line numberDiff line change
@@ -1574,10 +1574,10 @@ namespace ts {
15741574
return a.fileName === b.fileName;
15751575
}
15761576

1577-
function moduleNameIsEqualTo(a: StringLiteral | Identifier, b: StringLiteral | Identifier): boolean {
1578-
return a.kind === SyntaxKind.StringLiteral
1579-
? b.kind === SyntaxKind.StringLiteral && a.text === b.text
1580-
: b.kind === SyntaxKind.Identifier && a.escapedText === b.escapedText;
1577+
function moduleNameIsEqualTo(a: StringLiteralLike | Identifier, b: StringLiteralLike | Identifier): boolean {
1578+
return a.kind === SyntaxKind.Identifier
1579+
? b.kind === SyntaxKind.Identifier && a.escapedText === b.escapedText
1580+
: b.kind === SyntaxKind.StringLiteral && a.text === b.text;
15811581
}
15821582

15831583
function collectExternalModuleReferences(file: SourceFile): void {
@@ -1589,7 +1589,7 @@ namespace ts {
15891589
const isExternalModuleFile = isExternalModule(file);
15901590

15911591
// file.imports may not be undefined if there exists dynamic import
1592-
let imports: StringLiteral[];
1592+
let imports: StringLiteralLike[] | undefined;
15931593
let moduleAugmentations: (StringLiteral | Identifier)[];
15941594
let ambientModules: string[];
15951595

@@ -1600,7 +1600,7 @@ namespace ts {
16001600
&& !file.isDeclarationFile) {
16011601
// synthesize 'import "tslib"' declaration
16021602
const externalHelpersModuleReference = createLiteral(externalHelpersModuleNameText);
1603-
const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined);
1603+
const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference);
16041604
addEmitFlags(importDecl, EmitFlags.NeverApplyImportHelper);
16051605
externalHelpersModuleReference.parent = importDecl;
16061606
importDecl.parent = file;
@@ -1621,66 +1621,55 @@ namespace ts {
16211621
return;
16221622

16231623
function collectModuleReferences(node: Statement, inAmbientModule: boolean): void {
1624-
switch (node.kind) {
1625-
case SyntaxKind.ImportDeclaration:
1626-
case SyntaxKind.ImportEqualsDeclaration:
1627-
case SyntaxKind.ExportDeclaration:
1628-
const moduleNameExpr = getExternalModuleName(node);
1629-
if (!moduleNameExpr || !isStringLiteral(moduleNameExpr)) {
1630-
break;
1631-
}
1632-
if (!moduleNameExpr.text) {
1633-
break;
1634-
}
1635-
1636-
// TypeScript 1.0 spec (April 2014): 12.1.6
1637-
// An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules
1638-
// only through top - level external module names. Relative external module names are not permitted.
1639-
if (!inAmbientModule || !isExternalModuleNameRelative(moduleNameExpr.text)) {
1640-
(imports || (imports = [])).push(moduleNameExpr);
1624+
if (isAnyImportOrReExport(node)) {
1625+
const moduleNameExpr = getExternalModuleName(node);
1626+
// TypeScript 1.0 spec (April 2014): 12.1.6
1627+
// An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules
1628+
// only through top - level external module names. Relative external module names are not permitted.
1629+
if (moduleNameExpr && isStringLiteral(moduleNameExpr) && moduleNameExpr.text && (!inAmbientModule || !isExternalModuleNameRelative(moduleNameExpr.text))) {
1630+
imports = append(imports, moduleNameExpr);
1631+
}
1632+
}
1633+
else if (isModuleDeclaration(node)) {
1634+
if (isAmbientModule(node) && (inAmbientModule || hasModifier(node, ModifierFlags.Ambient) || file.isDeclarationFile)) {
1635+
const nameText = getTextOfIdentifierOrLiteral(node.name);
1636+
// Ambient module declarations can be interpreted as augmentations for some existing external modules.
1637+
// This will happen in two cases:
1638+
// - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope
1639+
// - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name
1640+
// immediately nested in top level ambient module declaration .
1641+
if (isExternalModuleFile || (inAmbientModule && !isExternalModuleNameRelative(nameText))) {
1642+
(moduleAugmentations || (moduleAugmentations = [])).push(node.name);
16411643
}
1642-
break;
1643-
case SyntaxKind.ModuleDeclaration:
1644-
if (isAmbientModule(<ModuleDeclaration>node) && (inAmbientModule || hasModifier(node, ModifierFlags.Ambient) || file.isDeclarationFile)) {
1645-
const moduleName = (<ModuleDeclaration>node).name;
1646-
const nameText = getTextOfIdentifierOrLiteral(moduleName);
1647-
// Ambient module declarations can be interpreted as augmentations for some existing external modules.
1648-
// This will happen in two cases:
1649-
// - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope
1650-
// - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name
1651-
// immediately nested in top level ambient module declaration .
1652-
if (isExternalModuleFile || (inAmbientModule && !isExternalModuleNameRelative(nameText))) {
1653-
(moduleAugmentations || (moduleAugmentations = [])).push(moduleName);
1644+
else if (!inAmbientModule) {
1645+
if (file.isDeclarationFile) {
1646+
// for global .d.ts files record name of ambient module
1647+
(ambientModules || (ambientModules = [])).push(nameText);
16541648
}
1655-
else if (!inAmbientModule) {
1656-
if (file.isDeclarationFile) {
1657-
// for global .d.ts files record name of ambient module
1658-
(ambientModules || (ambientModules = [])).push(nameText);
1659-
}
1660-
// An AmbientExternalModuleDeclaration declares an external module.
1661-
// This type of declaration is permitted only in the global module.
1662-
// The StringLiteral must specify a top - level external module name.
1663-
// Relative external module names are not permitted
1664-
1665-
// NOTE: body of ambient module is always a module block, if it exists
1666-
const body = <ModuleBlock>(<ModuleDeclaration>node).body;
1667-
if (body) {
1668-
for (const statement of body.statements) {
1669-
collectModuleReferences(statement, /*inAmbientModule*/ true);
1670-
}
1649+
// An AmbientExternalModuleDeclaration declares an external module.
1650+
// This type of declaration is permitted only in the global module.
1651+
// The StringLiteral must specify a top - level external module name.
1652+
// Relative external module names are not permitted
1653+
1654+
// NOTE: body of ambient module is always a module block, if it exists
1655+
const body = <ModuleBlock>(<ModuleDeclaration>node).body;
1656+
if (body) {
1657+
for (const statement of body.statements) {
1658+
collectModuleReferences(statement, /*inAmbientModule*/ true);
16711659
}
16721660
}
16731661
}
1662+
}
16741663
}
16751664
}
16761665

16771666
function collectDynamicImportOrRequireCalls(node: Node): void {
1678-
if (isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) {
1679-
(imports || (imports = [])).push(<StringLiteral>(<CallExpression>node).arguments[0]);
1667+
if (isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) {
1668+
imports = append(imports, node.arguments[0]);
16801669
}
16811670
// we have to check the argument list has length of 1. We will still have to process these even though we have parsing error.
1682-
else if (isImportCall(node) && node.arguments.length === 1 && node.arguments[0].kind === SyntaxKind.StringLiteral) {
1683-
(imports || (imports = [])).push(<StringLiteral>(<CallExpression>node).arguments[0]);
1671+
else if (isImportCall(node) && node.arguments.length === 1 && isStringLiteralLike(node.arguments[0])) {
1672+
imports = append(imports, node.arguments[0] as StringLiteralLike);
16841673
}
16851674
else {
16861675
forEachChild(node, collectDynamicImportOrRequireCalls);

0 commit comments

Comments
 (0)