Skip to content

Commit d8d0c75

Browse files
committed
Merge branch 'master' of https://github.com/Microsoft/TypeScript
2 parents bef4d52 + 1c64943 commit d8d0c75

File tree

80 files changed

+2345
-657
lines changed

Some content is hidden

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

80 files changed

+2345
-657
lines changed

src/compiler/binder.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@ namespace ts {
703703
function isNarrowableReference(expr: Expression): boolean {
704704
return expr.kind === SyntaxKind.Identifier ||
705705
expr.kind === SyntaxKind.ThisKeyword ||
706+
expr.kind === SyntaxKind.SuperKeyword ||
706707
expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
707708
}
708709

@@ -1910,7 +1911,9 @@ namespace ts {
19101911
// Here the current node is "foo", which is a container, but the scope of "MyType" should
19111912
// not be inside "foo". Therefore we always bind @typedef before bind the parent node,
19121913
// and skip binding this tag later when binding all the other jsdoc tags.
1913-
bindJSDocTypedefTagIfAny(node);
1914+
if (isInJavaScriptFile(node)) {
1915+
bindJSDocTypedefTagIfAny(node);
1916+
}
19141917

19151918
// First we bind declaration nodes to a symbol if possible. We'll both create a symbol
19161919
// and then potentially add the symbol to an appropriate symbol table. Possible

src/compiler/checker.ts

+67-16
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,10 @@ namespace ts {
493493
return symbol;
494494
}
495495

496+
function isTransientSymbol(symbol: Symbol): symbol is TransientSymbol {
497+
return (symbol.flags & SymbolFlags.Transient) !== 0;
498+
}
499+
496500
function getExcludedSymbolFlags(flags: SymbolFlags): SymbolFlags {
497501
let result: SymbolFlags = 0;
498502
if (flags & SymbolFlags.BlockScopedVariable) result |= SymbolFlags.BlockScopedVariableExcludes;
@@ -717,7 +721,7 @@ namespace ts {
717721
}
718722
// declaration is after usage
719723
// can be legal if usage is deferred (i.e. inside function or in initializer of instance property)
720-
if (isUsedInFunctionOrInstanceProperty(usage)) {
724+
if (isUsedInFunctionOrInstanceProperty(usage, declaration)) {
721725
return true;
722726
}
723727
const sourceFiles = host.getSourceFiles();
@@ -748,8 +752,7 @@ namespace ts {
748752
// 1. inside a function
749753
// 2. inside an instance property initializer, a reference to a non-instance property
750754
const container = getEnclosingBlockScopeContainer(declaration);
751-
const isInstanceProperty = declaration.kind === SyntaxKind.PropertyDeclaration && !(getModifierFlags(declaration) & ModifierFlags.Static);
752-
return isUsedInFunctionOrInstanceProperty(usage, isInstanceProperty, container);
755+
return isUsedInFunctionOrInstanceProperty(usage, declaration, container);
753756

754757
function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean {
755758
const container = getEnclosingBlockScopeContainer(declaration);
@@ -778,7 +781,7 @@ namespace ts {
778781
return false;
779782
}
780783

781-
function isUsedInFunctionOrInstanceProperty(usage: Node, isDeclarationInstanceProperty?: boolean, container?: Node): boolean {
784+
function isUsedInFunctionOrInstanceProperty(usage: Node, declaration: Node, container?: Node): boolean {
782785
let current = usage;
783786
while (current) {
784787
if (current === container) {
@@ -795,7 +798,8 @@ namespace ts {
795798
(<PropertyDeclaration>current.parent).initializer === current;
796799

797800
if (initializerOfInstanceProperty) {
798-
return !isDeclarationInstanceProperty;
801+
const isDeclarationInstanceProperty = declaration.kind === SyntaxKind.PropertyDeclaration && !(getModifierFlags(declaration) & ModifierFlags.Static);
802+
return !isDeclarationInstanceProperty || getContainingClass(usage) !== getContainingClass(declaration);
799803
}
800804

801805
current = current.parent;
@@ -1540,9 +1544,9 @@ namespace ts {
15401544
}
15411545
}
15421546
else if (name.kind === SyntaxKind.ParenthesizedExpression) {
1543-
// If the expression in parenthsizedExpression is not an entity-name (e.g. it is a call expression), it won't be able to successfully resolve the name.
1544-
// This is the case when we are trying to do any language service operation in heritage clauses. By return undefined, the getSymbolOfEntityNameOrPropertyAccessExpression
1545-
// will attempt to checkPropertyAccessExpression to resolve symbol.
1547+
// If the expression in parenthesizedExpression is not an entity-name (e.g. it is a call expression), it won't be able to successfully resolve the name.
1548+
// This is the case when we are trying to do any language service operation in heritage clauses.
1549+
// By return undefined, the getSymbolOfEntityNameOrPropertyAccessExpression will attempt to checkPropertyAccessExpression to resolve symbol.
15461550
// i.e class C extends foo()./*do language service operation here*/B {}
15471551
return isEntityNameExpression(name.expression) ?
15481552
resolveEntityName(name.expression as EntityNameOrEntityNameExpression, meaning, ignoreErrors, dontResolveAlias, location) :
@@ -1560,7 +1564,7 @@ namespace ts {
15601564
}
15611565

15621566
function resolveExternalModuleNameWorker(location: Node, moduleReferenceExpression: Expression, moduleNotFoundError: DiagnosticMessage, isForAugmentation = false): Symbol {
1563-
if (moduleReferenceExpression.kind !== SyntaxKind.StringLiteral) {
1567+
if (moduleReferenceExpression.kind !== SyntaxKind.StringLiteral && moduleReferenceExpression.kind !== SyntaxKind.NoSubstitutionTemplateLiteral) {
15641568
return;
15651569
}
15661570

@@ -3385,23 +3389,23 @@ namespace ts {
33853389

33863390
function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
33873391
const parameterNode = <ParameterDeclaration>p.valueDeclaration;
3388-
if (isRestParameter(parameterNode)) {
3392+
if (parameterNode ? isRestParameter(parameterNode) : isTransientSymbol(p) && p.isRestParameter) {
33893393
writePunctuation(writer, SyntaxKind.DotDotDotToken);
33903394
}
3391-
if (isBindingPattern(parameterNode.name)) {
3395+
if (parameterNode && isBindingPattern(parameterNode.name)) {
33923396
buildBindingPatternDisplay(<BindingPattern>parameterNode.name, writer, enclosingDeclaration, flags, symbolStack);
33933397
}
33943398
else {
33953399
appendSymbolNameOnly(p, writer);
33963400
}
3397-
if (isOptionalParameter(parameterNode)) {
3401+
if (parameterNode && isOptionalParameter(parameterNode)) {
33983402
writePunctuation(writer, SyntaxKind.QuestionToken);
33993403
}
34003404
writePunctuation(writer, SyntaxKind.ColonToken);
34013405
writeSpace(writer);
34023406

34033407
let type = getTypeOfSymbol(p);
3404-
if (isRequiredInitializedParameter(parameterNode)) {
3408+
if (parameterNode && isRequiredInitializedParameter(parameterNode)) {
34053409
type = includeFalsyTypes(type, TypeFlags.Undefined);
34063410
}
34073411
buildTypeDisplay(type, writer, enclosingDeclaration, flags, symbolStack);
@@ -6170,6 +6174,37 @@ namespace ts {
61706174
}
61716175
}
61726176

6177+
function containsArgumentsReference(declaration: FunctionLikeDeclaration): boolean {
6178+
const links = getNodeLinks(declaration);
6179+
if (links.containsArgumentsReference === undefined) {
6180+
if (links.flags & NodeCheckFlags.CaptureArguments) {
6181+
links.containsArgumentsReference = true;
6182+
}
6183+
else {
6184+
links.containsArgumentsReference = traverse(declaration.body);
6185+
}
6186+
}
6187+
return links.containsArgumentsReference;
6188+
6189+
function traverse(node: Node): boolean {
6190+
if (!node) return false;
6191+
switch (node.kind) {
6192+
case SyntaxKind.Identifier:
6193+
return (<Identifier>node).text === "arguments" && isPartOfExpression(node);
6194+
6195+
case SyntaxKind.PropertyDeclaration:
6196+
case SyntaxKind.MethodDeclaration:
6197+
case SyntaxKind.GetAccessor:
6198+
case SyntaxKind.SetAccessor:
6199+
return (<Declaration>node).name.kind === SyntaxKind.ComputedPropertyName
6200+
&& traverse((<Declaration>node).name);
6201+
6202+
default:
6203+
return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && forEachChild(node, traverse);
6204+
}
6205+
}
6206+
}
6207+
61736208
function getSignaturesOfSymbol(symbol: Symbol): Signature[] {
61746209
if (!symbol) return emptyArray;
61756210
const result: Signature[] = [];
@@ -10347,6 +10382,8 @@ namespace ts {
1034710382
getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(<Identifier>source)) === getSymbolOfNode(target);
1034810383
case SyntaxKind.ThisKeyword:
1034910384
return target.kind === SyntaxKind.ThisKeyword;
10385+
case SyntaxKind.SuperKeyword:
10386+
return target.kind === SyntaxKind.SuperKeyword;
1035010387
case SyntaxKind.PropertyAccessExpression:
1035110388
return target.kind === SyntaxKind.PropertyAccessExpression &&
1035210389
(<PropertyAccessExpression>source).name.text === (<PropertyAccessExpression>target).name.text &&
@@ -11483,6 +11520,7 @@ namespace ts {
1148311520
switch (expr.kind) {
1148411521
case SyntaxKind.Identifier:
1148511522
case SyntaxKind.ThisKeyword:
11523+
case SyntaxKind.SuperKeyword:
1148611524
case SyntaxKind.PropertyAccessExpression:
1148711525
return narrowTypeByTruthiness(type, expr, assumeTrue);
1148811526
case SyntaxKind.CallExpression:
@@ -11613,9 +11651,7 @@ namespace ts {
1161311651
}
1161411652
}
1161511653

11616-
if (node.flags & NodeFlags.AwaitContext) {
11617-
getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments;
11618-
}
11654+
getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments;
1161911655
return getTypeOfSymbol(symbol);
1162011656
}
1162111657

@@ -14854,6 +14890,21 @@ namespace ts {
1485414890
}
1485514891
}
1485614892

14893+
if (signatures.length === 1) {
14894+
const declaration = signatures[0].declaration;
14895+
if (declaration && isInJavaScriptFile(declaration) && !hasJSDocParameterTags(declaration)) {
14896+
if (containsArgumentsReference(<FunctionLikeDeclaration>declaration)) {
14897+
const signatureWithRest = cloneSignature(signatures[0]);
14898+
const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args");
14899+
syntheticArgsSymbol.type = anyArrayType;
14900+
syntheticArgsSymbol.isRestParameter = true;
14901+
signatureWithRest.parameters = concatenate(signatureWithRest.parameters, [syntheticArgsSymbol]);
14902+
signatureWithRest.hasRestParameter = true;
14903+
signatures = [signatureWithRest];
14904+
}
14905+
}
14906+
}
14907+
1485714908
const candidates = candidatesOutArray || [];
1485814909
// reorderCandidates fills up the candidates array directly
1485914910
reorderCandidates(signatures, candidates);

src/compiler/parser.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,7 @@ namespace ts {
12671267
function nextTokenIsClassOrFunctionOrAsync(): boolean {
12681268
nextToken();
12691269
return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.FunctionKeyword ||
1270+
(token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) ||
12701271
(token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine));
12711272
}
12721273

@@ -4661,6 +4662,11 @@ namespace ts {
46614662
return tokenIsIdentifierOrKeyword(token()) && !scanner.hasPrecedingLineBreak();
46624663
}
46634664

4665+
function nextTokenIsClassKeywordOnSameLine() {
4666+
nextToken();
4667+
return token() === SyntaxKind.ClassKeyword && !scanner.hasPrecedingLineBreak();
4668+
}
4669+
46644670
function nextTokenIsFunctionKeywordOnSameLine() {
46654671
nextToken();
46664672
return token() === SyntaxKind.FunctionKeyword && !scanner.hasPrecedingLineBreak();
@@ -6528,7 +6534,7 @@ namespace ts {
65286534

65296535
function parseTagComments(indent: number) {
65306536
const comments: string[] = [];
6531-
let state = JSDocState.SawAsterisk;
6537+
let state = JSDocState.BeginningOfLine;
65326538
let margin: number | undefined;
65336539
function pushComment(text: string) {
65346540
if (!margin) {

src/compiler/types.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -2870,6 +2870,7 @@ namespace ts {
28702870
/* @internal */
28712871
export interface TransientSymbol extends Symbol, SymbolLinks {
28722872
checkFlags: CheckFlags;
2873+
isRestParameter?: boolean;
28732874
}
28742875

28752876
export type SymbolTable = Map<Symbol>;
@@ -2899,7 +2900,7 @@ namespace ts {
28992900
ContextChecked = 0x00000400, // Contextual types have been assigned
29002901
AsyncMethodWithSuper = 0x00000800, // An async method that reads a value from a member of 'super'.
29012902
AsyncMethodWithSuperBinding = 0x00001000, // An async method that assigns a value to a member of 'super'.
2902-
CaptureArguments = 0x00002000, // Lexical 'arguments' used in body (for async functions)
2903+
CaptureArguments = 0x00002000, // Lexical 'arguments' used in body
29032904
EnumValuesComputed = 0x00004000, // Values for enum members have been computed, and any errors have been reported for them.
29042905
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
29052906
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
@@ -2923,6 +2924,7 @@ namespace ts {
29232924
maybeTypePredicate?: boolean; // Cached check whether call expression might reference a type predicate
29242925
enumMemberValue?: number; // Constant value of enum member
29252926
isVisible?: boolean; // Is this node visible
2927+
containsArgumentsReference?: boolean; // Whether a function-like declaration contains an 'arguments' reference
29262928
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
29272929
jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with
29282930
resolvedJsxElementAttributesType?: Type; // resolved element attributes type of a JSX openinglike element

src/compiler/utilities.ts

+17-10
Original file line numberDiff line numberDiff line change
@@ -1404,17 +1404,24 @@ namespace ts {
14041404

14051405
/**
14061406
* Returns true if the node is a CallExpression to the identifier 'require' with
1407-
* exactly one argument.
1407+
* exactly one argument (of the form 'require("name")').
14081408
* This function does not test if the node is in a JavaScript file or not.
1409-
*/
1410-
export function isRequireCall(expression: Node, checkArgumentIsStringLiteral: boolean): expression is CallExpression {
1411-
// of the form 'require("name")'
1412-
const isRequire = expression.kind === SyntaxKind.CallExpression &&
1413-
(<CallExpression>expression).expression.kind === SyntaxKind.Identifier &&
1414-
(<Identifier>(<CallExpression>expression).expression).text === "require" &&
1415-
(<CallExpression>expression).arguments.length === 1;
1409+
*/
1410+
export function isRequireCall(callExpression: Node, checkArgumentIsStringLiteral: boolean): callExpression is CallExpression {
1411+
if (callExpression.kind !== SyntaxKind.CallExpression) {
1412+
return false;
1413+
}
1414+
const { expression, arguments } = callExpression as CallExpression;
1415+
1416+
if (expression.kind !== SyntaxKind.Identifier || (expression as Identifier).text !== "require") {
1417+
return false;
1418+
}
14161419

1417-
return isRequire && (!checkArgumentIsStringLiteral || (<CallExpression>expression).arguments[0].kind === SyntaxKind.StringLiteral);
1420+
if (arguments.length !== 1) {
1421+
return false;
1422+
}
1423+
const arg = arguments[0];
1424+
return !checkArgumentIsStringLiteral || arg.kind === SyntaxKind.StringLiteral || arg.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
14181425
}
14191426

14201427
export function isSingleOrDoubleQuote(charCode: number) {
@@ -1588,7 +1595,7 @@ namespace ts {
15881595
return node && firstOrUndefined(getJSDocTags(node, kind));
15891596
}
15901597

1591-
function getJSDocs(node: Node): (JSDoc | JSDocTag)[] {
1598+
export function getJSDocs(node: Node): (JSDoc | JSDocTag)[] {
15921599
let cache: (JSDoc | JSDocTag)[] = node.jsDocCache;
15931600
if (!cache) {
15941601
getJSDocsWorker(node);

0 commit comments

Comments
 (0)