Skip to content

Commit 3b721e7

Browse files
author
Andy Hanson
committed
Merge branch 'master' into undefinedzilla
2 parents 34906ef + d4a166d commit 3b721e7

File tree

137 files changed

+3353
-1565
lines changed

Some content is hidden

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

137 files changed

+3353
-1565
lines changed

package-lock.json

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

scripts/processDiagnosticMessages.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
interface DiagnosticDetails {
55
category: string;
66
code: number;
7+
reportsUnnecessary?: {};
78
isEarly?: boolean;
89
}
910

@@ -59,14 +60,15 @@ function buildInfoFileOutput(messageTable: InputDiagnosticMessageTable, inputFil
5960
"/// <reference path=\"types.ts\" />\r\n" +
6061
"/* @internal */\r\n" +
6162
"namespace ts {\r\n" +
62-
" function diag(code: number, category: DiagnosticCategory, key: string, message: string): DiagnosticMessage {\r\n" +
63-
" return { code, category, key, message };\r\n" +
63+
" function diag(code: number, category: DiagnosticCategory, key: string, message: string, reportsUnnecessary?: {}): DiagnosticMessage {\r\n" +
64+
" return { code, category, key, message, reportsUnnecessary };\r\n" +
6465
" }\r\n" +
6566
" // tslint:disable-next-line variable-name\r\n" +
6667
" export const Diagnostics = {\r\n";
67-
messageTable.forEach(({ code, category }, name) => {
68+
messageTable.forEach(({ code, category, reportsUnnecessary }, name) => {
6869
const propName = convertPropertyName(name);
69-
result += ` ${propName}: diag(${code}, DiagnosticCategory.${category}, "${createKey(propName, code)}", ${JSON.stringify(name)}),\r\n`;
70+
const argReportsUnnecessary = reportsUnnecessary ? `, /*reportsUnnecessary*/ ${reportsUnnecessary}` : "";
71+
result += ` ${propName}: diag(${code}, DiagnosticCategory.${category}, "${createKey(propName, code)}", ${JSON.stringify(name)}${argReportsUnnecessary}),\r\n`;
7072
});
7173

7274
result += " };\r\n}";

scripts/tslint/rules/booleanTriviaRule.ts

+2-5
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,11 @@ function walk(ctx: Lint.WalkContext<void>): void {
2828
function shouldIgnoreCalledExpression(expression: ts.Expression): boolean {
2929
if (expression.kind === ts.SyntaxKind.PropertyAccessExpression) {
3030
const methodName = (expression as ts.PropertyAccessExpression).name.text;
31-
if (methodName.indexOf("set") === 0) {
31+
if (methodName.startsWith("set") || methodName.startsWith("assert")) {
3232
return true;
3333
}
3434
switch (methodName) {
3535
case "apply":
36-
case "assert":
37-
case "assertEqual":
3836
case "call":
3937
case "equal":
4038
case "fail":
@@ -46,11 +44,10 @@ function walk(ctx: Lint.WalkContext<void>): void {
4644
}
4745
else if (expression.kind === ts.SyntaxKind.Identifier) {
4846
const functionName = (expression as ts.Identifier).text;
49-
if (functionName.indexOf("set") === 0) {
47+
if (functionName.startsWith("set") || functionName.startsWith("assert")) {
5048
return true;
5149
}
5250
switch (functionName) {
53-
case "assert":
5451
case "contains":
5552
case "createAnonymousType":
5653
case "createImportSpecifier":

src/compiler/checker.ts

+19-7
Original file line numberDiff line numberDiff line change
@@ -4187,14 +4187,17 @@ namespace ts {
41874187
else {
41884188
// Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form)
41894189
const name = declaration.propertyName || <Identifier>declaration.name;
4190-
if (isComputedNonLiteralName(name)) {
4191-
// computed properties with non-literal names are treated as 'any'
4190+
const isLate = isLateBindableName(name);
4191+
const isWellKnown = isComputedPropertyName(name) && isWellKnownSymbolSyntactically(name.expression);
4192+
if (!isLate && !isWellKnown && isComputedNonLiteralName(name)) {
41924193
return anyType;
41934194
}
41944195

41954196
// Use type of the specified property, or otherwise, for a numeric name, the type of the numeric index signature,
41964197
// or otherwise the type of the string index signature.
4197-
const text = getTextOfPropertyName(name);
4198+
const text = isLate ? getLateBoundNameFromType(checkComputedPropertyName(name as ComputedPropertyName) as LiteralType | UniqueESSymbolType) :
4199+
isWellKnown ? getPropertyNameForKnownSymbolName(idText(((name as ComputedPropertyName).expression as PropertyAccessExpression).name)) :
4200+
getTextOfPropertyName(name);
41984201

41994202
// Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation
42004203
if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) {
@@ -4380,7 +4383,7 @@ namespace ts {
43804383
for (const declaration of symbol.declarations!) {
43814384
let declarationInConstructor = false;
43824385
const expression = declaration.kind === SyntaxKind.BinaryExpression ? <BinaryExpression>declaration :
4383-
declaration.kind === SyntaxKind.PropertyAccessExpression ? <BinaryExpression>getAncestor(declaration, SyntaxKind.BinaryExpression) :
4386+
declaration.kind === SyntaxKind.PropertyAccessExpression ? cast(declaration.parent, isBinaryExpression) :
43844387
undefined;
43854388

43864389
if (!expression) {
@@ -13921,7 +13924,8 @@ namespace ts {
1392113924
const assignmentKind = getAssignmentTargetKind(node);
1392213925

1392313926
if (assignmentKind) {
13924-
if (!(localOrExportSymbol.flags & SymbolFlags.Variable)) {
13927+
if (!(localOrExportSymbol.flags & SymbolFlags.Variable) &&
13928+
!(isInJavaScriptFile(node) && localOrExportSymbol.flags & SymbolFlags.ValueModule)) {
1392513929
error(node, Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable, symbolToString(symbol));
1392613930
return unknownType;
1392713931
}
@@ -19137,6 +19141,9 @@ namespace ts {
1913719141

1913819142
const links = getNodeLinks(node);
1913919143
const type = getTypeOfSymbol(node.symbol!);
19144+
if (isTypeAny(type)) {
19145+
return type;
19146+
}
1914019147

1914119148
// Check if function expression is contextually typed and assign parameter types if so.
1914219149
if (!(links.flags! & NodeCheckFlags.ContextChecked)) {
@@ -19902,8 +19909,9 @@ namespace ts {
1990219909
// VarExpr = ValueExpr
1990319910
// requires VarExpr to be classified as a reference
1990419911
// A compound assignment furthermore requires VarExpr to be classified as a reference (section 4.1)
19905-
// and the type of the non - compound operation to be assignable to the type of VarExpr.
19906-
if (checkReferenceExpression(left, Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access)) {
19912+
// and the type of the non-compound operation to be assignable to the type of VarExpr.
19913+
if (checkReferenceExpression(left, Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access)
19914+
&& (!isIdentifier(left) || unescapeLeadingUnderscores(left.escapedText) !== "exports")) {
1990719915
// to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported
1990819916
checkTypeAssignableTo(valueType, leftType, left, /*headMessage*/ undefined);
1990919917
}
@@ -21927,6 +21935,10 @@ namespace ts {
2192721935
// and give a better error message when the host function mentions `arguments`
2192821936
// but the tag doesn't have an array type
2192921937
if (decl) {
21938+
const i = getJSDocTags(decl).filter(isJSDocParameterTag).indexOf(node);
21939+
if (i > -1 && i < decl.parameters.length && isBindingPattern(decl.parameters[i].name)) {
21940+
return;
21941+
}
2193021942
if (!containsArgumentsReference(decl)) {
2193121943
error(node.name,
2193221944
Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name,

src/compiler/core.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -1299,14 +1299,11 @@ namespace ts {
12991299
});
13001300
}
13011301

1302-
export function assign<T1 extends MapLike<{}>, T2, T3>(t: T1, arg1: T2, arg2: T3): T1 & T2 & T3;
1303-
export function assign<T1 extends MapLike<{}>, T2>(t: T1, arg1: T2): T1 & T2;
1304-
export function assign<T1 extends MapLike<{}>>(t: T1, ...args: any[]): any;
1305-
export function assign<T1 extends MapLike<{}>>(t: T1, ...args: any[]) {
1302+
export function assign<T extends object>(t: T, ...args: (T | undefined)[]) {
13061303
for (const arg of args) {
1307-
for (const p in arg) {
1308-
if (hasProperty(arg, p)) {
1309-
t[p] = arg[p];
1304+
for (const p in arg!) {
1305+
if (hasProperty(arg!, p)) {
1306+
t![p] = arg![p]; // TODO: GH#23368
13101307
}
13111308
}
13121309
}
@@ -1635,7 +1632,7 @@ namespace ts {
16351632
messageText: text,
16361633
category: message.category,
16371634
code: message.code,
1638-
reportsUnnecessary: message.unused,
1635+
reportsUnnecessary: message.reportsUnnecessary,
16391636
};
16401637
}
16411638

@@ -1666,7 +1663,7 @@ namespace ts {
16661663
messageText: text,
16671664
category: message.category,
16681665
code: message.code,
1669-
reportsUnnecessary: message.unused,
1666+
reportsUnnecessary: message.reportsUnnecessary,
16701667
};
16711668
}
16721669

@@ -1756,6 +1753,10 @@ namespace ts {
17561753
return compareComparableValues(a, b);
17571754
}
17581755

1756+
export function min<T>(a: T, b: T, compare: Comparer<T>): T {
1757+
return compare(a, b) === Comparison.LessThan ? a : b;
1758+
}
1759+
17591760
/**
17601761
* Compare two strings using a case-insensitive ordinal comparison.
17611762
*
@@ -3152,8 +3153,8 @@ namespace ts {
31523153
return (arg: T) => f(arg) && g(arg);
31533154
}
31543155

3155-
export function or<T>(f: (arg: T) => boolean, g: (arg: T) => boolean) {
3156-
return (arg: T) => f(arg) || g(arg);
3156+
export function or<T>(f: (arg: T) => boolean, g: (arg: T) => boolean): (arg: T) => boolean {
3157+
return arg => f(arg) || g(arg);
31573158
}
31583159

31593160
export function assertTypeIsNever(_: never): void { } // tslint:disable-line no-empty

src/compiler/diagnosticMessages.json

+8-4
Original file line numberDiff line numberDiff line change
@@ -3286,7 +3286,7 @@
32863286
"'{0}' is declared but its value is never read.": {
32873287
"category": "Error",
32883288
"code": 6133,
3289-
"unused": true
3289+
"reportsUnnecessary": true
32903290
},
32913291
"Report errors on unused locals.": {
32923292
"category": "Message",
@@ -3307,7 +3307,7 @@
33073307
"Property '{0}' is declared but its value is never read.": {
33083308
"category": "Error",
33093309
"code": 6138,
3310-
"unused": true
3310+
"reportsUnnecessary": true
33113311
},
33123312
"Import emit helpers from 'tslib'.": {
33133313
"category": "Message",
@@ -3520,7 +3520,7 @@
35203520
"All imports in import declaration are unused.": {
35213521
"category": "Error",
35223522
"code": 6192,
3523-
"unused": true
3523+
"reportsUnnecessary": true
35243524
},
35253525
"Found 1 error.": {
35263526
"category": "Message",
@@ -3609,7 +3609,7 @@
36093609
"Unused label.": {
36103610
"category": "Error",
36113611
"code": 7028,
3612-
"unused": true
3612+
"reportsUnnecessary": true
36133613
},
36143614
"Fallthrough case in switch.": {
36153615
"category": "Error",
@@ -4161,5 +4161,9 @@
41614161
"Convert all constructor functions to classes": {
41624162
"category": "Message",
41634163
"code": 95045
4164+
},
4165+
"Generate 'get' and 'set' accessors": {
4166+
"category": "Message",
4167+
"code": 95046
41644168
}
41654169
}

src/compiler/parser.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -7603,7 +7603,7 @@ namespace ts {
76037603
const tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im;
76047604
const singleLinePragmaRegEx = /^\/\/\/?\s*@(\S+)\s*(.*)\s*$/im;
76057605
function extractPragmas(pragmas: PragmaPsuedoMapEntry[], range: CommentRange, text: string) {
7606-
const tripleSlash = tripleSlashXMLCommentStartRegEx.exec(text);
7606+
const tripleSlash = range.kind === SyntaxKind.SingleLineCommentTrivia && tripleSlashXMLCommentStartRegEx.exec(text);
76077607
if (tripleSlash) {
76087608
const name = tripleSlash[1].toLowerCase() as keyof PragmaPsuedoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks
76097609
const pragma = commentPragmas[name] as PragmaDefinition;
@@ -7640,15 +7640,17 @@ namespace ts {
76407640
return;
76417641
}
76427642

7643-
const singleLine = singleLinePragmaRegEx.exec(text);
7643+
const singleLine = range.kind === SyntaxKind.SingleLineCommentTrivia && singleLinePragmaRegEx.exec(text);
76447644
if (singleLine) {
76457645
return addPragmaForMatch(pragmas, range, PragmaKindFlags.SingleLine, singleLine);
76467646
}
76477647

7648-
const multiLinePragmaRegEx = /\s*@(\S+)\s*(.*)\s*$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating)
7649-
let multiLineMatch: RegExpExecArray | null;
7650-
while (multiLineMatch = multiLinePragmaRegEx.exec(text)) {
7651-
addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch);
7648+
if (range.kind === SyntaxKind.MultiLineCommentTrivia) {
7649+
const multiLinePragmaRegEx = /\s*@(\S+)\s*(.*)\s*$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating)
7650+
let multiLineMatch: RegExpExecArray | null;
7651+
while (multiLineMatch = multiLinePragmaRegEx.exec(text)) {
7652+
addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch);
7653+
}
76527654
}
76537655
}
76547656

src/compiler/program.ts

-1
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,6 @@ namespace ts {
578578
const packageIdToSourceFile = createMap<SourceFile>();
579579
// Maps from a SourceFile's `.path` to the name of the package it was imported with.
580580
let sourceFileToPackageName = createMap<string>();
581-
// See `sourceFileIsRedirectedTo`.
582581
let redirectTargetsSet = createMap<true>();
583582

584583
const filesByName = createMap<SourceFile | undefined>();

src/compiler/tsc.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace ts {
2222
}
2323

2424
let reportDiagnostic = createDiagnosticReporter(sys);
25-
function udpateReportDiagnostic(options: CompilerOptions) {
25+
function updateReportDiagnostic(options: CompilerOptions) {
2626
if (options.pretty) {
2727
reportDiagnostic = createDiagnosticReporter(sys, /*pretty*/ true);
2828
}
@@ -111,7 +111,7 @@ namespace ts {
111111
const commandLineOptions = commandLine.options;
112112
if (configFileName) {
113113
const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic)!; // TODO: GH#18217
114-
udpateReportDiagnostic(configParseResult.options);
114+
updateReportDiagnostic(configParseResult.options);
115115
if (isWatchSet(configParseResult.options)) {
116116
reportWatchModeWithoutSysSupport();
117117
createWatchOfConfigFile(configParseResult, commandLineOptions);
@@ -121,7 +121,7 @@ namespace ts {
121121
}
122122
}
123123
else {
124-
udpateReportDiagnostic(commandLineOptions);
124+
updateReportDiagnostic(commandLineOptions);
125125
if (isWatchSet(commandLineOptions)) {
126126
reportWatchModeWithoutSysSupport();
127127
createWatchOfFilesAndCompilerOptions(commandLine.fileNames, commandLineOptions);

src/compiler/types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2527,7 +2527,7 @@ namespace ts {
25272527
/**
25282528
* If two source files are for the same version of the same package, one will redirect to the other.
25292529
* (See `createRedirectSourceFile` in program.ts.)
2530-
* The redirect will have this set. The other will not have anything set, but see Program#sourceFileIsRedirectedTo.
2530+
* The redirect will have this set. The redirected-to source file will be in `redirectTargetsSet`.
25312531
*/
25322532
/* @internal */ redirectInfo?: RedirectInfo | undefined;
25332533

@@ -4079,7 +4079,7 @@ namespace ts {
40794079
category: DiagnosticCategory;
40804080
code: number;
40814081
message: string;
4082-
unused?: {};
4082+
reportsUnnecessary?: {};
40834083
}
40844084

40854085
/**

src/compiler/utilities.ts

+15-5
Original file line numberDiff line numberDiff line change
@@ -4287,7 +4287,7 @@ namespace ts {
42874287
}
42884288
}
42894289

4290-
export function isParameterPropertyDeclaration(node: Node): boolean {
4290+
export function isParameterPropertyDeclaration(node: Node): node is ParameterDeclaration {
42914291
return hasModifier(node, ModifierFlags.ParameterPropertyModifier) && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent);
42924292
}
42934293

@@ -4649,11 +4649,21 @@ namespace ts {
46494649
* parameters by name and binding patterns do not have a name.
46504650
*/
46514651
export function getJSDocParameterTags(param: ParameterDeclaration): ReadonlyArray<JSDocParameterTag> {
4652-
if (param.name && isIdentifier(param.name)) {
4653-
const name = param.name.escapedText;
4654-
return getJSDocTags(param.parent).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && isIdentifier(tag.name) && tag.name.escapedText === name);
4652+
if (param.name) {
4653+
if (isIdentifier(param.name)) {
4654+
const name = param.name.escapedText;
4655+
return getJSDocTags(param.parent).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && isIdentifier(tag.name) && tag.name.escapedText === name);
4656+
}
4657+
else {
4658+
const i = param.parent.parameters.indexOf(param);
4659+
Debug.assert(i > -1, "Parameters should always be in their parents' parameter list");
4660+
const paramTags = getJSDocTags(param.parent).filter(isJSDocParameterTag);
4661+
if (i < paramTags.length) {
4662+
return [paramTags[i]];
4663+
}
4664+
}
46554665
}
4656-
// a binding pattern doesn't have a name, so it's not possible to match it a JSDoc parameter, which is identified by name
4666+
// return empty array for: out-of-order binding patterns and JSDoc function syntax, which has un-named parameters
46574667
return emptyArray;
46584668
}
46594669

src/harness/fourslash.ts

+16
Original file line numberDiff line numberDiff line change
@@ -1081,8 +1081,20 @@ namespace FourSlash {
10811081
}
10821082
}
10831083

1084+
private verifyDocumentHighlightsRespectFilesList(files: ReadonlyArray<string>): void {
1085+
const startFile = this.activeFile.fileName;
1086+
for (const fileName of files) {
1087+
const searchFileNames = startFile === fileName ? [startFile] : [startFile, fileName];
1088+
const highlights = this.getDocumentHighlightsAtCurrentPosition(searchFileNames)!;
1089+
if (!highlights.every(dh => ts.contains(searchFileNames, dh.fileName))) {
1090+
this.raiseError(`When asking for document highlights only in files ${searchFileNames}, got document highlights in ${unique(highlights, dh => dh.fileName)}`);
1091+
}
1092+
}
1093+
}
1094+
10841095
public verifyReferencesOf(range: Range, references: Range[]) {
10851096
this.goToRangeStart(range);
1097+
this.verifyDocumentHighlightsRespectFilesList(unique(references, e => e.fileName));
10861098
this.verifyReferencesAre(references);
10871099
}
10881100

@@ -1128,6 +1140,10 @@ namespace FourSlash {
11281140
};
11291141
});
11301142
this.assertObjectsEqual(fullActual, fullExpected);
1143+
1144+
if (parts) {
1145+
this.verifyDocumentHighlightsRespectFilesList(unique(ts.flatMap(parts, p => p.ranges), r => r.fileName));
1146+
}
11311147
}
11321148
}
11331149

0 commit comments

Comments
 (0)