Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b980026

Browse files
committedMay 9, 2019
fix: Interpolated String Nesting
1 parent f51e835 commit b980026

File tree

2 files changed

+87
-27
lines changed

2 files changed

+87
-27
lines changed
 

‎src/Viasfora.Languages/BraceScanners/CSharpBraceScanner.cs

+54-21
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using Winterdom.Viasfora.Rainbow;
45
using Winterdom.Viasfora.Util;
@@ -11,11 +12,34 @@ public class CSharpBraceScanner : IBraceScanner, IResumeControl {
1112
const int stMultiLineComment = 4;
1213
const int stIString = 5;
1314

14-
private int status = stText;
15-
private int nestingLevel = 0;
16-
private int istringNestLevel = 0;
17-
private bool parsingExpression = false;
18-
private bool multiLine = false;
15+
private int status { get => this.nestings[this._nestingIndex].status; set => this.nestings[this._nestingIndex].status = value; }
16+
private int nestingLevel { get => this.nestings[this._nestingIndex].nestingLevel; set => this.nestings[this._nestingIndex].nestingLevel = value; }
17+
private bool parsingExpression { get => this.nestings[this._nestingIndex].parsingExpression; set => this.nestings[this._nestingIndex].parsingExpression = value; }
18+
private bool multiLine { get => this.nestings[this._nestingIndex].multiLine; set => this.nestings[this._nestingIndex].multiLine = value; }
19+
20+
21+
private int nestingIndex {
22+
get {
23+
return this._nestingIndex;
24+
}
25+
set {
26+
if ( value > this._nestingIndex ) {
27+
this.nestings.Add(new NestingOption() {status = this.status, nestingLevel = this.nestingLevel, parsingExpression = this.parsingExpression, multiLine=this.multiLine});
28+
} else if(value < this._nestingIndex) {
29+
this.nestings.RemoveAt(this.nestings.Count-1);
30+
}
31+
this._nestingIndex = value;
32+
}
33+
}
34+
private int _nestingIndex = 0;
35+
private List<NestingOption> nestings = new List<NestingOption>() { new NestingOption() };
36+
37+
private class NestingOption {
38+
public int nestingLevel = 0;
39+
public int status = stText;
40+
public bool parsingExpression = false;
41+
public bool multiLine = false;
42+
}
1943

2044
public String BraceList => "(){}[]";
2145

@@ -27,7 +51,7 @@ public void Reset(int state) {
2751
this.parsingExpression = (state & 0x08000000) != 0;
2852
this.nestingLevel = (state & 0xFF0000) >> 24;
2953
this.multiLine = (state & 0x04000000) != 0;
30-
this.istringNestLevel = (state & 0xFF00) >> 16;
54+
this.nestingIndex = (state & 0xFF00) >> 16;
3155
}
3256

3357
public bool CanResume(CharPos brace) {
@@ -170,17 +194,18 @@ private bool ParseInterpolatedString(ITextChars tc, ref CharPos pos) {
170194
//
171195
// we're inside an interpolated section
172196
//
173-
if ( tc.Char() == '$' && tc.NChar() == '"' ) {
197+
if ( tc.Char() == '$' && (tc.NChar() == '"') || (tc.NNChar() == '"' && tc.NChar() == '@') ) {
174198
// opening nested interpolated string
175-
tc.Skip(2);
199+
tc.Skip(tc.NChar() == '"' ? 2 : 3);
200+
this.nestingIndex++;
176201
this.parsingExpression = false;
177-
this.istringNestLevel++;
178202
this.nestingLevel = 0;
179-
if ( this.ParseInterpolatedString(tc, ref pos) )
180-
return true;
181-
this.istringNestLevel--;
182-
this.parsingExpression = true;
183-
this.status = stIString;
203+
//if ( this.ParseInterpolatedString(tc, ref pos) )
204+
// return true;
205+
//this.nestingIndex--;
206+
//this.parsingExpression = true;
207+
//this.status = stIString;
208+
return false;
184209
} else if ( tc.Char() == '@' && tc.NChar() == '"' ) {
185210
// opening nested verbatim string
186211
tc.Skip(2);
@@ -234,15 +259,23 @@ private bool ParseInterpolatedString(ITextChars tc, ref CharPos pos) {
234259
tc.Skip(2);
235260
} else if ( tc.Char() == '"' ) {
236261
// done parsing the interpolated string
237-
this.multiLine = false;
238-
this.istringNestLevel--;
239-
if (this.istringNestLevel <= 0) {
240-
this.istringNestLevel = 0;
262+
//this.multiLine = false;
263+
//if ( this.nestingIndex - 1 <= 0 ) {
264+
// this.nestingIndex = 0;
265+
// this.status = stText;
266+
//} else {
267+
// this.status = stIString;
268+
// this.parsingExpression = true;
269+
//}
270+
var indx = this.nestingIndex;
271+
if(indx -1 < 0) {
272+
this.multiLine = false;
273+
this.nestingIndex = 0;
241274
this.status = stText;
242275
} else {
243-
this.status = stIString;
244-
this.parsingExpression = true;
276+
this.nestingIndex--;
245277
}
278+
246279
tc.Next();
247280
break;
248281
} else {
@@ -260,7 +293,7 @@ private int EncodedState() {
260293
if ( this.multiLine )
261294
encoded |= 0x04000000;
262295
encoded |= (this.nestingLevel & 0xFF) << 24;
263-
encoded |= (this.istringNestLevel & 0xFF) << 16;
296+
encoded |= (this.nestingIndex & 0xFF) << 16;
264297
return encoded;
265298
}
266299
}

‎tests/Viasfora.Tests/BraceScanners/CSharpBraceScannerTests.cs

+33-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24
using Winterdom.Viasfora.Languages.BraceScanners;
35
using Xunit;
46

@@ -153,14 +155,39 @@ public void Bug128_InterpolatedStringWithNestedCurlyBraces() {
153155
var chars = Extract(extractor, input.Trim(), 0, 0);
154156
Assert.Equal(1+1+2+1+1+1+1, chars.Count);
155157
}
156-
[Fact]
157-
public void Bug259_InterpolatedStringEmbedded() {
158-
String input = "$\"{(string.IsNullOrWhiteSpace(a) ? $\"{b}\" : $\"{c}\")}\"";
159-
var extractor = new CSharpBraceScanner();
160-
var chars = Extract(extractor, input.Trim(), 0, 0);
161-
Assert.Equal(2+1+1+1+1+1+1+2, chars.Count);
158+
[Fact]
159+
public void Bug259_InterpolatedStringEmbedded() {
160+
String input = "$\"{(string.IsNullOrWhiteSpace(a) ? $\"{b}\" : $\"{c}\")}\"";
161+
var extractor = new CSharpBraceScanner();
162+
var chars = Extract(extractor, input.Trim(), 0, 0);
163+
Assert.Equal(2+1+1+1+1+1+1+2, chars.Count);
164+
}
165+
166+
public List<string> testList = new List<string>();
167+
168+
[Fact]
169+
public void Bug263_InterpolatedStringWithInterpolatedString1() {
170+
171+
// bug is the missing ) in following section of the teststring:
172+
// n => $\"pre_{n}_suf\").Aggregate
173+
174+
String input = "string.IsNullOrEmpty($\"{test} {(string.IsNullOrEmpty(test) ? \"\" : testList.Select(n => $\"pre_{n}_suf\").Aggregate((n,m) => n + \", \" + m))}\")";
175+
var extractor = new CSharpBraceScanner();
176+
var chars = Extract(extractor, input.Trim(), 0, 0);
177+
Assert.Equal(1+1+1+2+1+1+1+1+1+1+2+1+3+1, chars.Count);
162178
}
179+
180+
[Fact]
181+
public void Bug263_InterpolatedStringWithInterpolatedString2() {
163182

183+
// bug is the missing ) in following section of the teststring:
184+
// n => $\"pre_{n}_suf\").Aggregate
185+
186+
String input = "string.IsNullOrEmpty($\"{test} {(string.IsNullOrEmpty(test) ? \"\" : testList.Select(n => $@\"pre_{n}_suf\").Aggregate((n,m) => n + \", \" + m))}\")";
187+
var extractor = new CSharpBraceScanner();
188+
var chars = Extract(extractor, input.Trim(), 0, 0);
189+
Assert.Equal(1 + 1 + 1 + 2 + 1 + 1 + 1 + 1 + 1 + 1 + 2 + 1 + 3 + 1, chars.Count);
190+
}
164191

165192
[Fact]
166193
public void InterpolatedAtString1() {

0 commit comments

Comments
 (0)
Please sign in to comment.