Skip to content

Commit cef5062

Browse files
Fixed issue where classifier didn't check for backslash-newline.
1 parent 86c7def commit cef5062

7 files changed

Lines changed: 150 additions & 7 deletions

src/services/services.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5549,15 +5549,24 @@ module ts {
55495549
addResult(end - start, classFromKind(token));
55505550

55515551
if (end >= text.length) {
5552-
// We're at the end.
55535552
if (token === SyntaxKind.StringLiteral) {
55545553
// Check to see if we finished up on a multiline string literal.
55555554
var tokenText = scanner.getTokenText();
55565555
if (scanner.isUnterminated()) {
5557-
var quoteChar = tokenText.charCodeAt(0);
5558-
result.finalLexState = quoteChar === CharacterCodes.doubleQuote
5559-
? EndOfLineState.InDoubleQuoteStringLiteral
5560-
: EndOfLineState.InSingleQuoteStringLiteral;
5556+
var lastCharIndex = tokenText.length - 1;
5557+
5558+
var numBackslashes = 0;
5559+
while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === CharacterCodes.backslash) {
5560+
numBackslashes++;
5561+
}
5562+
5563+
// If we have an odd number of backslashes, then the multiline string is unclosed
5564+
if (numBackslashes & 1) {
5565+
var quoteChar = tokenText.charCodeAt(0);
5566+
result.finalLexState = quoteChar === CharacterCodes.doubleQuote
5567+
? EndOfLineState.InDoubleQuoteStringLiteral
5568+
: EndOfLineState.InSingleQuoteStringLiteral;
5569+
}
55615570
}
55625571
}
55635572
else if (token === SyntaxKind.MultiLineCommentTrivia) {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////"/*1*/ /*2*/\/*3*/
4+
//// /*4*/ \\/*5*/
5+
6+
test.markers().forEach(marker => {
7+
goTo.position(marker.position);
8+
9+
verify.completionListIsEmpty()
10+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////"/*1*/ /*2*/\/*3*/
4+
//// /*4*/ \\\/*5*/
5+
//// /*6*/
6+
7+
test.markers().forEach(marker => {
8+
goTo.position(marker.position);
9+
10+
verify.completionListIsEmpty()
11+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// function f(templateStrings, x, y, z) { return 10; }
4+
//// function g(templateStrings, x, y, z) { return ""; }
5+
////
6+
//// f ` ${ 123 } /*1*/${ } /*2*/\/*3*/
7+
//// /*4*/\\/*5*/
8+
//// /*6*/\\\/*7*/
9+
//// /*8*/
10+
11+
test.markers().forEach(m => {
12+
goTo.position(m.position);
13+
14+
verify.signatureHelpCountIs(1);
15+
verify.signatureHelpArgumentCountIs(1);
16+
17+
verify.currentSignatureParameterCountIs(4);
18+
verify.currentSignatureHelpIs('f(templateStrings: any, x: any, y: any, z: any): number');
19+
verify.currentParameterHelpArgumentNameIs("templateStrings");
20+
verify.currentParameterSpanIs("templateStrings: any");
21+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// function f(templateStrings, x, y, z) { return 10; }
4+
//// function g(templateStrings, x, y, z) { return ""; }
5+
////
6+
//// f `/*1*/\/*2*/`/*3*/ /*4*/
7+
8+
test.markers().forEach(m => {
9+
goTo.position(m.position);
10+
11+
verify.signatureHelpCountIs(1);
12+
verify.signatureHelpArgumentCountIs(1);
13+
14+
verify.currentSignatureParameterCountIs(4);
15+
verify.currentSignatureHelpIs('f(templateStrings: any, x: any, y: any, z: any): number');
16+
verify.currentParameterHelpArgumentNameIs("templateStrings");
17+
verify.currentParameterSpanIs("templateStrings: any");
18+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// function f(templateStrings, x, y, z) { return 10; }
4+
//// function g(templateStrings, x, y, z) { return ""; }
5+
////
6+
//// f `/*1*/ \\\/*2*/`/*3*/ /*4*/
7+
8+
test.markers().forEach(m => {
9+
goTo.position(m.position);
10+
11+
verify.signatureHelpCountIs(1);
12+
verify.signatureHelpArgumentCountIs(1);
13+
14+
verify.currentSignatureParameterCountIs(4);
15+
verify.currentSignatureHelpIs('f(templateStrings: any, x: any, y: any, z: any): number');
16+
verify.currentParameterHelpArgumentNameIs("templateStrings");
17+
verify.currentParameterSpanIs("templateStrings: any");
18+
});

tests/cases/unittests/services/colorization.ts

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,20 +130,76 @@ describe('Colorization', function () {
130130
operator(","));
131131
});
132132

133-
it("correctly classifies an unterminated multi-line string", function () {
133+
it("correctly classifies a multi-line string with one backslash", function () {
134134
test("'line1\\",
135135
ts.EndOfLineState.Start,
136136
stringLiteral("'line1\\"),
137137
finalEndOfLineState(ts.EndOfLineState.InSingleQuoteStringLiteral));
138138
});
139139

140-
it("correctly classifies the second line of an unterminated multi-line string", function () {
140+
it("correctly classifies a multi-line string with three backslashes", function () {
141+
test("'line1\\\\\\",
142+
ts.EndOfLineState.Start,
143+
stringLiteral("'line1\\\\\\"),
144+
finalEndOfLineState(ts.EndOfLineState.InSingleQuoteStringLiteral));
145+
});
146+
147+
it("correctly classifies an unterminated single-line string with no backslashes", function () {
148+
test("'line1",
149+
ts.EndOfLineState.Start,
150+
stringLiteral("'line1"),
151+
finalEndOfLineState(ts.EndOfLineState.Start));
152+
});
153+
154+
it("correctly classifies an unterminated single-line string with two backslashes", function () {
155+
test("'line1\\\\",
156+
ts.EndOfLineState.Start,
157+
stringLiteral("'line1\\\\"),
158+
finalEndOfLineState(ts.EndOfLineState.Start));
159+
});
160+
161+
it("correctly classifies an unterminated single-line string with four backslashes", function () {
162+
test("'line1\\\\\\\\",
163+
ts.EndOfLineState.Start,
164+
stringLiteral("'line1\\\\\\\\"),
165+
finalEndOfLineState(ts.EndOfLineState.Start));
166+
});
167+
168+
it("correctly classifies the continuing line of a multi-line string ending in one backslash", function () {
169+
test("\\",
170+
ts.EndOfLineState.InDoubleQuoteStringLiteral,
171+
stringLiteral("\\"),
172+
finalEndOfLineState(ts.EndOfLineState.InDoubleQuoteStringLiteral));
173+
});
174+
175+
it("correctly classifies the continuing line of a multi-line string ending in three backslashes", function () {
141176
test("\\",
142177
ts.EndOfLineState.InDoubleQuoteStringLiteral,
143178
stringLiteral("\\"),
144179
finalEndOfLineState(ts.EndOfLineState.InDoubleQuoteStringLiteral));
145180
});
146181

182+
it("correctly classifies the last line of an unterminated multi-line string ending in no backslashes", function () {
183+
test(" ",
184+
ts.EndOfLineState.InDoubleQuoteStringLiteral,
185+
stringLiteral(" "),
186+
finalEndOfLineState(ts.EndOfLineState.Start));
187+
});
188+
189+
it("correctly classifies the last line of an unterminated multi-line string ending in two backslashes", function () {
190+
test("\\\\",
191+
ts.EndOfLineState.InDoubleQuoteStringLiteral,
192+
stringLiteral("\\\\"),
193+
finalEndOfLineState(ts.EndOfLineState.Start));
194+
});
195+
196+
it("correctly classifies the last line of an unterminated multi-line string ending in four backslashes", function () {
197+
test("\\\\\\\\",
198+
ts.EndOfLineState.InDoubleQuoteStringLiteral,
199+
stringLiteral("\\\\\\\\"),
200+
finalEndOfLineState(ts.EndOfLineState.Start));
201+
});
202+
147203
it("correctly classifies the last line of a multi-line string", function () {
148204
test("'",
149205
ts.EndOfLineState.InSingleQuoteStringLiteral,

0 commit comments

Comments
 (0)