Skip to content

Commit 4e79458

Browse files
committed
Merge branch 'master' into es6typings
Conflicts: tests/baselines/reference/constDeclarationShadowedByVarDeclaration3.types
2 parents 99d13f4 + 203e46c commit 4e79458

File tree

70 files changed

+860
-69
lines changed

Some content is hidden

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

70 files changed

+860
-69
lines changed

src/compiler/checker.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,8 @@ module ts {
16081608
return isDeclarationVisible(<Declaration>parent);
16091609

16101610
case SyntaxKind.Property:
1611+
case SyntaxKind.GetAccessor:
1612+
case SyntaxKind.SetAccessor:
16111613
case SyntaxKind.Method:
16121614
if (node.flags & (NodeFlags.Private | NodeFlags.Protected)) {
16131615
// Private/protected properties/methods are not visible
@@ -1622,6 +1624,14 @@ module ts {
16221624
case SyntaxKind.Parameter:
16231625
case SyntaxKind.ModuleBlock:
16241626
case SyntaxKind.TypeParameter:
1627+
case SyntaxKind.FunctionType:
1628+
case SyntaxKind.ConstructorType:
1629+
case SyntaxKind.TypeLiteral:
1630+
case SyntaxKind.TypeReference:
1631+
case SyntaxKind.ArrayType:
1632+
case SyntaxKind.TupleType:
1633+
case SyntaxKind.UnionType:
1634+
case SyntaxKind.ParenthesizedType:
16251635
return isDeclarationVisible(<Declaration>node.parent);
16261636

16271637
// Source file is always visible
@@ -5335,15 +5345,15 @@ module ts {
53355345
var templateExpression = <TemplateExpression>tagExpression.template;
53365346
var lastSpan = lastOrUndefined(templateExpression.templateSpans);
53375347
Debug.assert(lastSpan !== undefined); // we should always have at least one span.
5338-
callIsIncomplete = lastSpan.literal.kind === SyntaxKind.Missing || isUnterminatedTemplateEnd(lastSpan.literal);
5348+
callIsIncomplete = lastSpan.literal.kind === SyntaxKind.Missing || !!lastSpan.literal.isUnterminated;
53395349
}
53405350
else {
53415351
// If the template didn't end in a backtick, or its beginning occurred right prior to EOF,
53425352
// then this might actually turn out to be a TemplateHead in the future;
53435353
// so we consider the call to be incomplete.
53445354
var templateLiteral = <LiteralExpression>tagExpression.template;
53455355
Debug.assert(templateLiteral.kind === SyntaxKind.NoSubstitutionTemplateLiteral);
5346-
callIsIncomplete = isUnterminatedTemplateEnd(templateLiteral);
5356+
callIsIncomplete = !!templateLiteral.isUnterminated;
53475357
}
53485358
}
53495359
else {

src/compiler/parser.ts

+4-19
Original file line numberDiff line numberDiff line change
@@ -855,25 +855,6 @@ module ts {
855855
return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
856856
}
857857

858-
export function isUnterminatedTemplateEnd(node: LiteralExpression) {
859-
Debug.assert(isTemplateLiteralKind(node.kind));
860-
var sourceText = getSourceFileOfNode(node).text;
861-
862-
// If we're not at the EOF, we know we must be terminated.
863-
if (node.end !== sourceText.length) {
864-
return false;
865-
}
866-
867-
// The literal can only be unterminated if it is a template tail or a no-sub template.
868-
if (node.kind !== SyntaxKind.TemplateTail && node.kind !== SyntaxKind.NoSubstitutionTemplateLiteral) {
869-
return false;
870-
}
871-
872-
// If we didn't end in a backtick, we must still be in the middle of a template.
873-
// If we did, make sure that it's not the *initial* backtick.
874-
return sourceText.charCodeAt(node.end - 1) !== CharacterCodes.backtick || node.text.length === 0;
875-
}
876-
877858
export function isModifier(token: SyntaxKind): boolean {
878859
switch (token) {
879860
case SyntaxKind.PublicKeyword:
@@ -1691,6 +1672,10 @@ module ts {
16911672
var text = scanner.getTokenValue();
16921673
node.text = internName ? internIdentifier(text) : text;
16931674

1675+
if (scanner.isUnterminated()) {
1676+
node.isUnterminated = true;
1677+
}
1678+
16941679
var tokenPos = scanner.getTokenPos();
16951680
nextToken();
16961681
finishNode(node);

src/compiler/scanner.ts

+10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module ts {
2222
hasPrecedingLineBreak(): boolean;
2323
isIdentifier(): boolean;
2424
isReservedWord(): boolean;
25+
isUnterminated(): boolean;
2526
reScanGreaterToken(): SyntaxKind;
2627
reScanSlashToken(): SyntaxKind;
2728
reScanTemplateToken(): SyntaxKind;
@@ -470,6 +471,7 @@ module ts {
470471
var token: SyntaxKind;
471472
var tokenValue: string;
472473
var precedingLineBreak: boolean;
474+
var tokenIsUnterminated: boolean;
473475

474476
function error(message: DiagnosticMessage): void {
475477
if (onError) {
@@ -553,6 +555,7 @@ module ts {
553555
while (true) {
554556
if (pos >= len) {
555557
result += text.substring(start, pos);
558+
tokenIsUnterminated = true;
556559
error(Diagnostics.Unterminated_string_literal);
557560
break;
558561
}
@@ -570,6 +573,7 @@ module ts {
570573
}
571574
if (isLineBreak(ch)) {
572575
result += text.substring(start, pos);
576+
tokenIsUnterminated = true;
573577
error(Diagnostics.Unterminated_string_literal);
574578
break;
575579
}
@@ -593,6 +597,7 @@ module ts {
593597
while (true) {
594598
if (pos >= len) {
595599
contents += text.substring(start, pos);
600+
tokenIsUnterminated = true;
596601
error(Diagnostics.Unterminated_template_literal);
597602
resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail;
598603
break;
@@ -780,6 +785,7 @@ module ts {
780785
function scan(): SyntaxKind {
781786
startPos = pos;
782787
precedingLineBreak = false;
788+
tokenIsUnterminated = false;
783789
while (true) {
784790
tokenPos = pos;
785791
if (pos >= len) {
@@ -936,6 +942,7 @@ module ts {
936942
continue;
937943
}
938944
else {
945+
tokenIsUnterminated = !commentClosed;
939946
return token = SyntaxKind.MultiLineCommentTrivia;
940947
}
941948
}
@@ -1113,12 +1120,14 @@ module ts {
11131120
// If we reach the end of a file, or hit a newline, then this is an unterminated
11141121
// regex. Report error and return what we have so far.
11151122
if (p >= len) {
1123+
tokenIsUnterminated = true;
11161124
error(Diagnostics.Unterminated_regular_expression_literal)
11171125
break;
11181126
}
11191127

11201128
var ch = text.charCodeAt(p);
11211129
if (isLineBreak(ch)) {
1130+
tokenIsUnterminated = true;
11221131
error(Diagnostics.Unterminated_regular_expression_literal)
11231132
break;
11241133
}
@@ -1211,6 +1220,7 @@ module ts {
12111220
hasPrecedingLineBreak: () => precedingLineBreak,
12121221
isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord,
12131222
isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord,
1223+
isUnterminated: () => tokenIsUnterminated,
12141224
reScanGreaterToken,
12151225
reScanSlashToken,
12161226
reScanTemplateToken,

src/compiler/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ module ts {
527527
// For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
528528
export interface LiteralExpression extends PrimaryExpression {
529529
text: string;
530+
isUnterminated?: boolean;
530531
}
531532

532533
export interface TemplateExpression extends PrimaryExpression {

src/lib/core.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,7 @@ interface RegExp {
836836
interface RegExpConstructor {
837837
new (pattern: string, flags?: string): RegExp;
838838
(pattern: string, flags?: string): RegExp;
839+
prototype: RegExp;
839840

840841
// Non-standard extensions
841842
$1: string;

src/lib/extensions.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ interface Map<K, V> {
631631
}
632632
declare var Map: {
633633
new <K, V>(): Map<K, V>;
634+
prototype: Map<any, any>;
634635
}
635636

636637
interface WeakMap<K, V> {
@@ -642,6 +643,7 @@ interface WeakMap<K, V> {
642643
}
643644
declare var WeakMap: {
644645
new <K, V>(): WeakMap<K, V>;
646+
prototype: WeakMap<any, any>;
645647
}
646648

647649
interface Set<T> {
@@ -654,4 +656,5 @@ interface Set<T> {
654656
}
655657
declare var Set: {
656658
new <T>(): Set<T>;
659+
prototype: Set<any>;
657660
}

src/services/formatting/formattingScanner.ts

+19-2
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,11 @@ module ts.formatting {
146146
if (lastTokenInfo && expectedScanAction === lastScanAction) {
147147
// readTokenInfo was called before with the same expected scan action.
148148
// No need to re-scan text, return existing 'lastTokenInfo'
149-
return lastTokenInfo;
149+
// it is ok to call fixTokenKind here since it does not affect
150+
// what portion of text is consumed. In opposize rescanning can change it,
151+
// i.e. for '>=' when originally scanner eats just one character
152+
// and rescanning forces it to consume more.
153+
return fixTokenKind(lastTokenInfo, n);
150154
}
151155

152156
if (scanner.getStartPos() !== savedPos) {
@@ -207,17 +211,30 @@ module ts.formatting {
207211
}
208212
}
209213

210-
return lastTokenInfo = {
214+
lastTokenInfo = {
211215
leadingTrivia: leadingTrivia,
212216
trailingTrivia: trailingTrivia,
213217
token: token
214218
}
219+
220+
return fixTokenKind(lastTokenInfo, n);
215221
}
216222

217223
function isOnToken(): boolean {
218224
var current = (lastTokenInfo && lastTokenInfo.token.kind) || scanner.getToken();
219225
var startPos = (lastTokenInfo && lastTokenInfo.token.pos) || scanner.getStartPos();
220226
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
221227
}
228+
229+
// when containing node in the tree is token
230+
// but its kind differs from the kind that was returned by the scanner,
231+
// then kind needs to be fixed. This might happen in cases
232+
// when parser interprets token differently, i.e keyword treated as identifier
233+
function fixTokenKind(tokenInfo: TokenInfo, container: Node): TokenInfo {
234+
if (isToken(container) && tokenInfo.token.kind !== container.kind) {
235+
tokenInfo.token.kind = container.kind;
236+
}
237+
return tokenInfo;
238+
}
222239
}
223240
}

src/services/services.ts

+21-41
Original file line numberDiff line numberDiff line change
@@ -2501,47 +2501,21 @@ module ts {
25012501
}
25022502

25032503
function isInStringOrRegularExpressionOrTemplateLiteral(previousToken: Node): boolean {
2504-
if (previousToken.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(previousToken.kind)) {
2504+
if (previousToken.kind === SyntaxKind.StringLiteral
2505+
|| previousToken.kind === SyntaxKind.RegularExpressionLiteral
2506+
|| isTemplateLiteralKind(previousToken.kind)) {
25052507
// The position has to be either: 1. entirely within the token text, or
2506-
// 2. at the end position, and the string literal is not terminated
2507-
2508+
// 2. at the end position of an unterminated token.
25082509
var start = previousToken.getStart();
25092510
var end = previousToken.getEnd();
25102511

25112512
if (start < position && position < end) {
25122513
return true;
25132514
}
25142515
else if (position === end) {
2515-
var width = end - start;
2516-
var text = previousToken.getSourceFile().text;
2517-
2518-
// If the token is a single character, or its second-to-last charcter indicates an escape code,
2519-
// then we can immediately say that we are in the middle of an unclosed string.
2520-
if (width <= 1 || text.charCodeAt(end - 2) === CharacterCodes.backslash) {
2521-
return true;
2522-
}
2523-
2524-
// Now check if the last character is a closing character for the token.
2525-
switch (previousToken.kind) {
2526-
case SyntaxKind.StringLiteral:
2527-
case SyntaxKind.NoSubstitutionTemplateLiteral:
2528-
return text.charCodeAt(start) !== text.charCodeAt(end - 1);
2529-
2530-
case SyntaxKind.TemplateHead:
2531-
case SyntaxKind.TemplateMiddle:
2532-
return text.charCodeAt(end - 1) !== CharacterCodes.openBrace
2533-
|| text.charCodeAt(end - 2) !== CharacterCodes.$;
2534-
2535-
case SyntaxKind.TemplateTail:
2536-
return text.charCodeAt(end - 1) !== CharacterCodes.backtick;
2537-
}
2538-
2539-
return false;
2516+
return !!(<LiteralExpression>previousToken).isUnterminated;
25402517
}
25412518
}
2542-
else if (previousToken.kind === SyntaxKind.RegularExpressionLiteral) {
2543-
return previousToken.getStart() < position && position < previousToken.getEnd();
2544-
}
25452519

25462520
return false;
25472521
}
@@ -5665,23 +5639,29 @@ module ts {
56655639
addResult(end - start, classFromKind(token));
56665640

56675641
if (end >= text.length) {
5668-
// We're at the end.
56695642
if (token === SyntaxKind.StringLiteral) {
56705643
// Check to see if we finished up on a multiline string literal.
56715644
var tokenText = scanner.getTokenText();
5672-
if (tokenText.length > 0 && tokenText.charCodeAt(tokenText.length - 1) === CharacterCodes.backslash) {
5673-
var quoteChar = tokenText.charCodeAt(0);
5674-
result.finalLexState = quoteChar === CharacterCodes.doubleQuote
5675-
? EndOfLineState.InDoubleQuoteStringLiteral
5676-
: EndOfLineState.InSingleQuoteStringLiteral;
5645+
if (scanner.isUnterminated()) {
5646+
var lastCharIndex = tokenText.length - 1;
5647+
5648+
var numBackslashes = 0;
5649+
while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === CharacterCodes.backslash) {
5650+
numBackslashes++;
5651+
}
5652+
5653+
// If we have an odd number of backslashes, then the multiline string is unclosed
5654+
if (numBackslashes & 1) {
5655+
var quoteChar = tokenText.charCodeAt(0);
5656+
result.finalLexState = quoteChar === CharacterCodes.doubleQuote
5657+
? EndOfLineState.InDoubleQuoteStringLiteral
5658+
: EndOfLineState.InSingleQuoteStringLiteral;
5659+
}
56775660
}
56785661
}
56795662
else if (token === SyntaxKind.MultiLineCommentTrivia) {
56805663
// Check to see if the multiline comment was unclosed.
5681-
var tokenText = scanner.getTokenText()
5682-
if (!(tokenText.length > 3 && // need to avoid catching '/*/'
5683-
tokenText.charCodeAt(tokenText.length - 2) === CharacterCodes.asterisk &&
5684-
tokenText.charCodeAt(tokenText.length - 1) === CharacterCodes.slash)) {
5664+
if (scanner.isUnterminated()) {
56855665
result.finalLexState = EndOfLineState.InMultiLineCommentTrivia;
56865666
}
56875667
}

src/services/signatureHelp.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ module ts.SignatureHelp {
296296
Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
297297

298298
// If we're just after a template tail, don't show signature help.
299-
if (node.kind === SyntaxKind.TemplateTail && position >= node.getEnd() && !isUnterminatedTemplateEnd(<LiteralExpression>node)) {
299+
if (node.kind === SyntaxKind.TemplateTail && position >= node.getEnd() && !(<LiteralExpression>node).isUnterminated) {
300300
return undefined;
301301
}
302302

src/services/utilities.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ module ts {
322322
}
323323

324324
export function isInsideTemplateLiteral(node: LiteralExpression, position: number) {
325-
return (node.getStart() < position && position < node.getEnd())
326-
|| (isUnterminatedTemplateEnd(node) && position === node.getEnd());
325+
return isTemplateLiteralKind(node.kind)
326+
&& (node.getStart() < position && position < node.getEnd()) || (!!node.isUnterminated && position === node.getEnd());
327327
}
328328
}

0 commit comments

Comments
 (0)