Skip to content

Commit f28fbfd

Browse files
committed
Merge branch 'master' into tscJsFiles
2 parents 6882035 + c05297c commit f28fbfd

Some content is hidden

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

51 files changed

+2218
-64
lines changed

src/compiler/binder.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,9 @@ namespace ts {
185185
function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol {
186186
Debug.assert(!hasDynamicName(node));
187187

188+
let isDefaultExport = node.flags & NodeFlags.Default;
188189
// The exported symbol for an export default function/class node is always named "default"
189-
let name = node.flags & NodeFlags.Default && parent ? "default" : getDeclarationName(node);
190+
let name = isDefaultExport && parent ? "default" : getDeclarationName(node);
190191

191192
let symbol: Symbol;
192193
if (name !== undefined) {
@@ -227,6 +228,13 @@ namespace ts {
227228
let message = symbol.flags & SymbolFlags.BlockScopedVariable
228229
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
229230
: Diagnostics.Duplicate_identifier_0;
231+
232+
forEach(symbol.declarations, declaration => {
233+
if (declaration.flags & NodeFlags.Default) {
234+
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
235+
}
236+
});
237+
230238
forEach(symbol.declarations, declaration => {
231239
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
232240
});

src/compiler/checker.ts

+72-31
Large diffs are not rendered by default.

src/compiler/diagnosticMessages.json

+8
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,10 @@
800800
"category": "Error",
801801
"code": 1311
802802
},
803+
"'=' can only be used in an object literal property inside a destructuring assignment.": {
804+
"category": "Error",
805+
"code": 1312
806+
},
803807
"Duplicate identifier '{0}'.": {
804808
"category": "Error",
805809
"code": 2300
@@ -1656,6 +1660,10 @@
16561660
"category": "Error",
16571661
"code": 2527
16581662
},
1663+
"A module cannot have multiple default exports.": {
1664+
"category": "Error",
1665+
"code": 2528
1666+
},
16591667
"JSX element attributes type '{0}' must be an object type.": {
16601668
"category": "Error",
16611669
"code": 2600

src/compiler/emitter.ts

+17-5
Original file line numberDiff line numberDiff line change
@@ -2309,6 +2309,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
23092309
write(": ");
23102310
emit(node.name);
23112311
}
2312+
2313+
if (languageVersion >= ScriptTarget.ES6 && node.objectAssignmentInitializer) {
2314+
write(" = ");
2315+
emit(node.objectAssignmentInitializer);
2316+
}
23122317
}
23132318

23142319
function tryEmitConstantValue(node: PropertyAccessExpression | ElementAccessExpression): boolean {
@@ -3572,7 +3577,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
35723577
for (let p of properties) {
35733578
if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
35743579
let propName = <Identifier | LiteralExpression>(<PropertyAssignment>p).name;
3575-
emitDestructuringAssignment((<PropertyAssignment>p).initializer || propName, createPropertyAccessForDestructuringProperty(value, propName));
3580+
let target = p.kind === SyntaxKind.ShorthandPropertyAssignment ? <ShorthandPropertyAssignment>p : (<PropertyAssignment>p).initializer || propName;
3581+
emitDestructuringAssignment(target, createPropertyAccessForDestructuringProperty(value, propName));
35763582
}
35773583
}
35783584
}
@@ -3597,8 +3603,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
35973603
}
35983604
}
35993605

3600-
function emitDestructuringAssignment(target: Expression, value: Expression) {
3601-
if (target.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>target).operatorToken.kind === SyntaxKind.EqualsToken) {
3606+
function emitDestructuringAssignment(target: Expression | ShorthandPropertyAssignment, value: Expression) {
3607+
if (target.kind === SyntaxKind.ShorthandPropertyAssignment) {
3608+
if ((<ShorthandPropertyAssignment>target).objectAssignmentInitializer) {
3609+
value = createDefaultValueCheck(value, (<ShorthandPropertyAssignment>target).objectAssignmentInitializer);
3610+
}
3611+
target = (<ShorthandPropertyAssignment>target).name;
3612+
}
3613+
else if (target.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>target).operatorToken.kind === SyntaxKind.EqualsToken) {
36023614
value = createDefaultValueCheck(value, (<BinaryExpression>target).right);
36033615
target = (<BinaryExpression>target).left;
36043616
}
@@ -6845,7 +6857,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
68456857
if (isLineBreak(c)) {
68466858
if (firstNonWhitespace !== -1 && (lastNonWhitespace - firstNonWhitespace + 1 > 0)) {
68476859
let part = text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1);
6848-
result = (result ? result + "\" + ' ' + \"" : "") + part;
6860+
result = (result ? result + "\" + ' ' + \"" : "") + escapeString(part);
68496861
}
68506862
firstNonWhitespace = -1;
68516863
}
@@ -6859,7 +6871,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
68596871

68606872
if (firstNonWhitespace !== -1) {
68616873
let part = text.substr(firstNonWhitespace);
6862-
result = (result ? result + "\" + ' ' + \"" : "") + part;
6874+
result = (result ? result + "\" + ' ' + \"" : "") + escapeString(part);
68636875
}
68646876

68656877
if (result) {

src/compiler/parser.ts

+21-3
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,17 @@ namespace ts {
5757
return visitNode(cbNode, (<TypeParameterDeclaration>node).name) ||
5858
visitNode(cbNode, (<TypeParameterDeclaration>node).constraint) ||
5959
visitNode(cbNode, (<TypeParameterDeclaration>node).expression);
60+
case SyntaxKind.ShorthandPropertyAssignment:
61+
return visitNodes(cbNodes, node.decorators) ||
62+
visitNodes(cbNodes, node.modifiers) ||
63+
visitNode(cbNode, (<ShorthandPropertyAssignment>node).name) ||
64+
visitNode(cbNode, (<ShorthandPropertyAssignment>node).questionToken) ||
65+
visitNode(cbNode, (<ShorthandPropertyAssignment>node).equalsToken) ||
66+
visitNode(cbNode, (<ShorthandPropertyAssignment>node).objectAssignmentInitializer);
6067
case SyntaxKind.Parameter:
6168
case SyntaxKind.PropertyDeclaration:
6269
case SyntaxKind.PropertySignature:
6370
case SyntaxKind.PropertyAssignment:
64-
case SyntaxKind.ShorthandPropertyAssignment:
6571
case SyntaxKind.VariableDeclaration:
6672
case SyntaxKind.BindingElement:
6773
return visitNodes(cbNodes, node.decorators) ||
@@ -3762,11 +3768,23 @@ namespace ts {
37623768
return parseMethodDeclaration(fullStart, decorators, modifiers, asteriskToken, propertyName, questionToken);
37633769
}
37643770

3765-
// Parse to check if it is short-hand property assignment or normal property assignment
3766-
if ((token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBraceToken) && tokenIsIdentifier) {
3771+
// check if it is short-hand property assignment or normal property assignment
3772+
// NOTE: if token is EqualsToken it is interpreted as CoverInitializedName production
3773+
// CoverInitializedName[Yield] :
3774+
// IdentifierReference[?Yield] Initializer[In, ?Yield]
3775+
// this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern
3776+
const isShorthandPropertyAssignment =
3777+
tokenIsIdentifier && (token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBraceToken || token === SyntaxKind.EqualsToken);
3778+
3779+
if (isShorthandPropertyAssignment) {
37673780
let shorthandDeclaration = <ShorthandPropertyAssignment>createNode(SyntaxKind.ShorthandPropertyAssignment, fullStart);
37683781
shorthandDeclaration.name = <Identifier>propertyName;
37693782
shorthandDeclaration.questionToken = questionToken;
3783+
const equalsToken = parseOptionalToken(SyntaxKind.EqualsToken);
3784+
if (equalsToken) {
3785+
shorthandDeclaration.equalsToken = equalsToken;
3786+
shorthandDeclaration.objectAssignmentInitializer = allowInAnd(parseAssignmentExpressionOrHigher);
3787+
}
37703788
return finishNode(shorthandDeclaration);
37713789
}
37723790
else {

src/compiler/types.ts

+4
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,10 @@ namespace ts {
562562
export interface ShorthandPropertyAssignment extends ObjectLiteralElement {
563563
name: Identifier;
564564
questionToken?: Node;
565+
// used when ObjectLiteralExpression is used in ObjectAssignmentPattern
566+
// it is grammar error to appear in actual object initializer
567+
equalsToken?: Node;
568+
objectAssignmentInitializer?: Expression;
565569
}
566570

567571
// SyntaxKind.VariableDeclaration

src/harness/fourslash.ts

+13-6
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ namespace FourSlash {
100100
end: number;
101101
}
102102

103+
export import IndentStyle = ts.IndentStyle;
104+
103105
let entityMap: ts.Map<string> = {
104106
"&": "&amp;",
105107
"\"": "&quot;",
@@ -309,6 +311,7 @@ namespace FourSlash {
309311
TabSize: 4,
310312
NewLineCharacter: Harness.IO.newLine(),
311313
ConvertTabsToSpaces: true,
314+
IndentStyle: ts.IndentStyle.Smart,
312315
InsertSpaceAfterCommaDelimiter: true,
313316
InsertSpaceAfterSemicolonInForStatements: true,
314317
InsertSpaceBeforeAndAfterBinaryOperators: true,
@@ -1695,24 +1698,28 @@ namespace FourSlash {
16951698
}
16961699
}
16971700

1698-
private getIndentation(fileName: string, position: number): number {
1699-
return this.languageService.getIndentationAtPosition(fileName, position, this.formatCodeOptions);
1701+
private getIndentation(fileName: string, position: number, indentStyle: ts.IndentStyle): number {
1702+
1703+
let formatOptions = ts.clone(this.formatCodeOptions);
1704+
formatOptions.IndentStyle = indentStyle;
1705+
1706+
return this.languageService.getIndentationAtPosition(fileName, position, formatOptions);
17001707
}
17011708

1702-
public verifyIndentationAtCurrentPosition(numberOfSpaces: number) {
1709+
public verifyIndentationAtCurrentPosition(numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart) {
17031710
this.taoInvalidReason = "verifyIndentationAtCurrentPosition NYI";
17041711

1705-
let actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition);
1712+
let actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition, indentStyle);
17061713
let lineCol = this.getLineColStringAtPosition(this.currentCaretPosition);
17071714
if (actual !== numberOfSpaces) {
17081715
this.raiseError(`verifyIndentationAtCurrentPosition failed at ${lineCol} - expected: ${numberOfSpaces}, actual: ${actual}`);
17091716
}
17101717
}
17111718

1712-
public verifyIndentationAtPosition(fileName: string, position: number, numberOfSpaces: number) {
1719+
public verifyIndentationAtPosition(fileName: string, position: number, numberOfSpaces: number, indentStyle: ts.IndentStyle = ts.IndentStyle.Smart) {
17131720
this.taoInvalidReason = "verifyIndentationAtPosition NYI";
17141721

1715-
let actual = this.getIndentation(fileName, position);
1722+
let actual = this.getIndentation(fileName, position, indentStyle);
17161723
let lineCol = this.getLineColStringAtPosition(position);
17171724
if (actual !== numberOfSpaces) {
17181725
this.raiseError(`verifyIndentationAtPosition failed at ${lineCol} - expected: ${numberOfSpaces}, actual: ${actual}`);

src/lib/dom.generated.d.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -7893,6 +7893,10 @@ declare var Node: {
78937893
}
78947894

78957895
interface NodeFilter {
7896+
acceptNode(n: Node): number;
7897+
}
7898+
7899+
declare var NodeFilter: {
78967900
FILTER_ACCEPT: number;
78977901
FILTER_REJECT: number;
78987902
FILTER_SKIP: number;
@@ -7910,7 +7914,6 @@ interface NodeFilter {
79107914
SHOW_PROCESSING_INSTRUCTION: number;
79117915
SHOW_TEXT: number;
79127916
}
7913-
declare var NodeFilter: NodeFilter;
79147917

79157918
interface NodeIterator {
79167919
expandEntityReferences: boolean;

src/server/editorServices.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,7 @@ namespace ts.server {
11771177
TabSize: 4,
11781178
NewLineCharacter: ts.sys ? ts.sys.newLine : '\n',
11791179
ConvertTabsToSpaces: true,
1180+
IndentStyle: ts.IndentStyle.Smart,
11801181
InsertSpaceAfterCommaDelimiter: true,
11811182
InsertSpaceAfterSemicolonInForStatements: true,
11821183
InsertSpaceBeforeAndAfterBinaryOperators: true,
@@ -1187,7 +1188,6 @@ namespace ts.server {
11871188
PlaceOpenBraceOnNewLineForFunctions: false,
11881189
PlaceOpenBraceOnNewLineForControlBlocks: false,
11891190
}
1190-
11911191
}
11921192

11931193
export interface LineCollection {

src/server/session.ts

+1
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ namespace ts.server {
606606
TabSize: formatOptions.TabSize,
607607
NewLineCharacter: "\n",
608608
ConvertTabsToSpaces: formatOptions.ConvertTabsToSpaces,
609+
IndentStyle: ts.IndentStyle.Smart,
609610
};
610611
var indentPosition =
611612
compilerService.languageService.getIndentationAtPosition(file, position, editorOptions);

src/services/formatting/rules.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ namespace ts.formatting {
214214
public SpaceBetweenYieldOrYieldStarAndOperand: Rule;
215215

216216
// Async functions
217+
public SpaceBetweenAsyncAndOpenParen: Rule;
217218
public SpaceBetweenAsyncAndFunctionKeyword: Rule;
218219

219220
// Template strings
@@ -369,6 +370,7 @@ namespace ts.formatting {
369370
this.SpaceBetweenYieldOrYieldStarAndOperand = new Rule(RuleDescriptor.create4(Shared.TokenRange.FromTokens([SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken]), Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsYieldOrYieldStarWithOperand), RuleAction.Space));
370371

371372
// Async-await
373+
this.SpaceBetweenAsyncAndOpenParen = new Rule(RuleDescriptor.create1(SyntaxKind.AsyncKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsArrowFunctionContext, Rules.IsSameLineTokenContext), RuleAction.Space));
372374
this.SpaceBetweenAsyncAndFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.AsyncKeyword, SyntaxKind.FunctionKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space));
373375

374376
// template string
@@ -402,7 +404,7 @@ namespace ts.formatting {
402404
this.NoSpaceBeforeOpenParenInFuncCall,
403405
this.SpaceBeforeBinaryKeywordOperator, this.SpaceAfterBinaryKeywordOperator,
404406
this.SpaceAfterVoidOperator,
405-
this.SpaceBetweenAsyncAndFunctionKeyword,
407+
this.SpaceBetweenAsyncAndOpenParen, this.SpaceBetweenAsyncAndFunctionKeyword,
406408
this.SpaceBetweenTagAndTemplateString, this.NoSpaceAfterTemplateHeadAndMiddle, this.NoSpaceBeforeTemplateMiddleAndTail,
407409

408410
// TypeScript-specific rules
@@ -703,6 +705,10 @@ namespace ts.formatting {
703705
return context.currentTokenSpan.kind !== SyntaxKind.CommaToken;
704706
}
705707

708+
static IsArrowFunctionContext(context: FormattingContext): boolean {
709+
return context.contextNode.kind === SyntaxKind.ArrowFunction;
710+
}
711+
706712
static IsSameLineTokenContext(context: FormattingContext): boolean {
707713
return context.TokensAreOnSameLine();
708714
}

src/services/formatting/smartIndenter.ts

+29-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ namespace ts.formatting {
1313
return 0; // past EOF
1414
}
1515

16+
// no indentation when the indent style is set to none,
17+
// so we can return fast
18+
if (options.IndentStyle === IndentStyle.None) {
19+
return 0;
20+
}
21+
1622
let precedingToken = findPrecedingToken(position, sourceFile);
1723
if (!precedingToken) {
1824
return 0;
@@ -26,6 +32,26 @@ namespace ts.formatting {
2632

2733
let lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
2834

35+
// indentation is first non-whitespace character in a previous line
36+
// for block indentation, we should look for a line which contains something that's not
37+
// whitespace.
38+
if (options.IndentStyle === IndentStyle.Block) {
39+
40+
// move backwards until we find a line with a non-whitespace character,
41+
// then find the first non-whitespace character for that line.
42+
let current = position;
43+
while (current > 0){
44+
let char = sourceFile.text.charCodeAt(current);
45+
if (!isWhiteSpace(char) && !isLineBreak(char)) {
46+
break;
47+
}
48+
current--;
49+
}
50+
51+
let lineStart = ts.getLineStartPositionForPosition(current, sourceFile);
52+
return SmartIndenter.findFirstNonWhitespaceColumn(lineStart, current, sourceFile, options);
53+
}
54+
2955
if (precedingToken.kind === SyntaxKind.CommaToken && precedingToken.parent.kind !== SyntaxKind.BinaryExpression) {
3056
// previous token is comma that separates items in list - find the previous item and try to derive indentation from it
3157
let actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options);
@@ -218,7 +244,7 @@ namespace ts.formatting {
218244
function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFile): LineAndCharacter {
219245
return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
220246
}
221-
247+
222248
export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFile): boolean {
223249
if (parent.kind === SyntaxKind.IfStatement && (<IfStatement>parent).elseStatement === child) {
224250
let elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile);
@@ -319,7 +345,7 @@ namespace ts.formatting {
319345
}
320346

321347
return Value.Unknown;
322-
348+
323349
function getStartingExpression(node: PropertyAccessExpression | CallExpression | ElementAccessExpression) {
324350
while (true) {
325351
switch (node.kind) {
@@ -465,4 +491,4 @@ namespace ts.formatting {
465491
}
466492
}
467493
}
468-
}
494+
}

src/services/services.ts

+7
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,13 @@ namespace ts {
11891189
TabSize: number;
11901190
NewLineCharacter: string;
11911191
ConvertTabsToSpaces: boolean;
1192+
IndentStyle: IndentStyle;
1193+
}
1194+
1195+
export enum IndentStyle {
1196+
None = 0,
1197+
Block = 1,
1198+
Smart = 2,
11921199
}
11931200

11941201
export interface FormatCodeOptions extends EditorOptions {

0 commit comments

Comments
 (0)