Skip to content

Commit 4058518

Browse files
committed
Merge pull request #931 from Microsoft/newTreeBreakPoints
New tree break points
2 parents db9c9f1 + 3f2211f commit 4058518

File tree

82 files changed

+7805
-1310
lines changed

Some content is hidden

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

82 files changed

+7805
-1310
lines changed

Jakefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ var servicesSources = [
5555
].map(function (f) {
5656
return path.join(compilerDirectory, f);
5757
}).concat([
58+
"breakpoints.ts",
5859
"services.ts",
5960
"shims.ts",
6061
"signatureHelp.ts",

src/compiler/checker.ts

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -7856,77 +7856,6 @@ module ts {
78567856
return node.parent && node.parent.kind === SyntaxKind.TypeReference;
78577857
}
78587858

7859-
function isExpression(node: Node): boolean {
7860-
switch (node.kind) {
7861-
case SyntaxKind.ThisKeyword:
7862-
case SyntaxKind.SuperKeyword:
7863-
case SyntaxKind.NullKeyword:
7864-
case SyntaxKind.TrueKeyword:
7865-
case SyntaxKind.FalseKeyword:
7866-
case SyntaxKind.RegularExpressionLiteral:
7867-
case SyntaxKind.ArrayLiteral:
7868-
case SyntaxKind.ObjectLiteral:
7869-
case SyntaxKind.PropertyAccess:
7870-
case SyntaxKind.IndexedAccess:
7871-
case SyntaxKind.CallExpression:
7872-
case SyntaxKind.NewExpression:
7873-
case SyntaxKind.TypeAssertion:
7874-
case SyntaxKind.ParenExpression:
7875-
case SyntaxKind.FunctionExpression:
7876-
case SyntaxKind.ArrowFunction:
7877-
case SyntaxKind.PrefixOperator:
7878-
case SyntaxKind.PostfixOperator:
7879-
case SyntaxKind.BinaryExpression:
7880-
case SyntaxKind.ConditionalExpression:
7881-
case SyntaxKind.OmittedExpression:
7882-
return true;
7883-
case SyntaxKind.QualifiedName:
7884-
while (node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
7885-
return node.parent.kind === SyntaxKind.TypeQuery;
7886-
case SyntaxKind.Identifier:
7887-
if (node.parent.kind === SyntaxKind.TypeQuery) {
7888-
return true;
7889-
}
7890-
// Fall through
7891-
case SyntaxKind.NumericLiteral:
7892-
case SyntaxKind.StringLiteral:
7893-
var parent = node.parent;
7894-
switch (parent.kind) {
7895-
case SyntaxKind.VariableDeclaration:
7896-
case SyntaxKind.Parameter:
7897-
case SyntaxKind.Property:
7898-
case SyntaxKind.EnumMember:
7899-
case SyntaxKind.PropertyAssignment:
7900-
return (<VariableDeclaration>parent).initializer === node;
7901-
case SyntaxKind.ExpressionStatement:
7902-
case SyntaxKind.IfStatement:
7903-
case SyntaxKind.DoStatement:
7904-
case SyntaxKind.WhileStatement:
7905-
case SyntaxKind.ReturnStatement:
7906-
case SyntaxKind.WithStatement:
7907-
case SyntaxKind.SwitchStatement:
7908-
case SyntaxKind.CaseClause:
7909-
case SyntaxKind.ThrowStatement:
7910-
case SyntaxKind.SwitchStatement:
7911-
return (<ExpressionStatement>parent).expression === node;
7912-
case SyntaxKind.ForStatement:
7913-
return (<ForStatement>parent).initializer === node ||
7914-
(<ForStatement>parent).condition === node ||
7915-
(<ForStatement>parent).iterator === node;
7916-
case SyntaxKind.ForInStatement:
7917-
return (<ForInStatement>parent).variable === node ||
7918-
(<ForInStatement>parent).expression === node;
7919-
case SyntaxKind.TypeAssertion:
7920-
return node === (<TypeAssertion>parent).operand;
7921-
default:
7922-
if (isExpression(parent)) {
7923-
return true;
7924-
}
7925-
}
7926-
}
7927-
return false;
7928-
}
7929-
79307859
function isTypeNode(node: Node): boolean {
79317860
if (SyntaxKind.FirstTypeNode <= node.kind && node.kind <= SyntaxKind.LastTypeNode) {
79327861
return true;

src/compiler/parser.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,77 @@ module ts {
6767
return identifier.kind === SyntaxKind.Missing ? "(Missing)" : getTextOfNode(identifier);
6868
}
6969

70+
export function isExpression(node: Node): boolean {
71+
switch (node.kind) {
72+
case SyntaxKind.ThisKeyword:
73+
case SyntaxKind.SuperKeyword:
74+
case SyntaxKind.NullKeyword:
75+
case SyntaxKind.TrueKeyword:
76+
case SyntaxKind.FalseKeyword:
77+
case SyntaxKind.RegularExpressionLiteral:
78+
case SyntaxKind.ArrayLiteral:
79+
case SyntaxKind.ObjectLiteral:
80+
case SyntaxKind.PropertyAccess:
81+
case SyntaxKind.IndexedAccess:
82+
case SyntaxKind.CallExpression:
83+
case SyntaxKind.NewExpression:
84+
case SyntaxKind.TypeAssertion:
85+
case SyntaxKind.ParenExpression:
86+
case SyntaxKind.FunctionExpression:
87+
case SyntaxKind.ArrowFunction:
88+
case SyntaxKind.PrefixOperator:
89+
case SyntaxKind.PostfixOperator:
90+
case SyntaxKind.BinaryExpression:
91+
case SyntaxKind.ConditionalExpression:
92+
case SyntaxKind.OmittedExpression:
93+
return true;
94+
case SyntaxKind.QualifiedName:
95+
while (node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
96+
return node.parent.kind === SyntaxKind.TypeQuery;
97+
case SyntaxKind.Identifier:
98+
if (node.parent.kind === SyntaxKind.TypeQuery) {
99+
return true;
100+
}
101+
// Fall through
102+
case SyntaxKind.NumericLiteral:
103+
case SyntaxKind.StringLiteral:
104+
var parent = node.parent;
105+
switch (parent.kind) {
106+
case SyntaxKind.VariableDeclaration:
107+
case SyntaxKind.Parameter:
108+
case SyntaxKind.Property:
109+
case SyntaxKind.EnumMember:
110+
case SyntaxKind.PropertyAssignment:
111+
return (<VariableDeclaration>parent).initializer === node;
112+
case SyntaxKind.ExpressionStatement:
113+
case SyntaxKind.IfStatement:
114+
case SyntaxKind.DoStatement:
115+
case SyntaxKind.WhileStatement:
116+
case SyntaxKind.ReturnStatement:
117+
case SyntaxKind.WithStatement:
118+
case SyntaxKind.SwitchStatement:
119+
case SyntaxKind.CaseClause:
120+
case SyntaxKind.ThrowStatement:
121+
case SyntaxKind.SwitchStatement:
122+
return (<ExpressionStatement>parent).expression === node;
123+
case SyntaxKind.ForStatement:
124+
return (<ForStatement>parent).initializer === node ||
125+
(<ForStatement>parent).condition === node ||
126+
(<ForStatement>parent).iterator === node;
127+
case SyntaxKind.ForInStatement:
128+
return (<ForInStatement>parent).variable === node ||
129+
(<ForInStatement>parent).expression === node;
130+
case SyntaxKind.TypeAssertion:
131+
return node === (<TypeAssertion>parent).operand;
132+
default:
133+
if (isExpression(parent)) {
134+
return true;
135+
}
136+
}
137+
}
138+
return false;
139+
}
140+
70141
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
71142
node = getErrorSpanForNode(node);
72143
var file = getSourceFileOfNode(node);

src/harness/fourslash.ts

Lines changed: 88 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -985,15 +985,85 @@ module FourSlash {
985985
return item.parameters[currentParam];
986986
}
987987

988-
public getBreakpointStatementLocation(pos: number) {
989-
this.taoInvalidReason = 'getBreakpointStatementLocation NYI';
988+
private alignmentForExtraInfo = 50;
989+
990+
private spanInfoToString(pos: number, spanInfo: TypeScript.TextSpan, prefixString: string) {
991+
var resultString = "SpanInfo: " + JSON.stringify(spanInfo);
992+
if (spanInfo) {
993+
var spanString = this.activeFile.content.substr(spanInfo.start(), spanInfo.length());
994+
var spanLineMap = ts.getLineStarts(spanString);
995+
for (var i = 0; i < spanLineMap.length; i++) {
996+
if (!i) {
997+
resultString += "\n";
998+
}
999+
resultString += prefixString + spanString.substring(spanLineMap[i], spanLineMap[i + 1]);
1000+
}
1001+
resultString += "\n" + prefixString + ":=> (" + this.getLineColStringAtPosition(spanInfo.start()) + ") to (" + this.getLineColStringAtPosition(spanInfo.end()) + ")";
1002+
}
1003+
1004+
return resultString;
1005+
}
1006+
1007+
private baselineCurrentFileLocations(getSpanAtPos: (pos: number) => TypeScript.TextSpan): string {
1008+
var fileLineMap = ts.getLineStarts(this.activeFile.content);
1009+
var nextLine = 0;
1010+
var resultString = "";
1011+
var currentLine: string;
1012+
var previousSpanInfo: string;
1013+
var startColumn: number;
1014+
var length: number;
1015+
var prefixString = " >";
1016+
1017+
var addSpanInfoString = () => {
1018+
if (previousSpanInfo) {
1019+
resultString += currentLine;
1020+
var thisLineMarker = repeatString(startColumn, " ") + repeatString(length, "~");
1021+
thisLineMarker += repeatString(this.alignmentForExtraInfo - thisLineMarker.length - prefixString.length + 1, " ");
1022+
resultString += thisLineMarker;
1023+
resultString += "=> Pos: (" + (pos - length) + " to " + (pos - 1) + ") ";
1024+
resultString += " " + previousSpanInfo;
1025+
previousSpanInfo = undefined;
1026+
}
1027+
};
9901028

991-
var spanInfo = this.languageService.getBreakpointStatementAtPosition(this.activeFile.fileName, pos);
992-
var resultString = "\n**Pos: " + pos + " SpanInfo: " + JSON.stringify(spanInfo) + "\n** Statement: ";
993-
if (spanInfo !== null) {
994-
resultString = resultString + this.activeFile.content.substr(spanInfo.start(), spanInfo.length());
1029+
for (var pos = 0; pos < this.activeFile.content.length; pos++) {
1030+
if (pos === 0 || pos === fileLineMap[nextLine]) {
1031+
nextLine++;
1032+
addSpanInfoString();
1033+
if (resultString.length) {
1034+
resultString += "\n--------------------------------";
1035+
}
1036+
currentLine = "\n" + nextLine.toString() + repeatString(3 - nextLine.toString().length, " ") + ">" + this.activeFile.content.substring(pos, fileLineMap[nextLine]) + "\n ";
1037+
startColumn = 0;
1038+
length = 0;
1039+
}
1040+
var spanInfo = this.spanInfoToString(pos, getSpanAtPos(pos), prefixString);
1041+
if (previousSpanInfo && previousSpanInfo !== spanInfo) {
1042+
addSpanInfoString();
1043+
previousSpanInfo = spanInfo;
1044+
startColumn = startColumn + length;
1045+
length = 1;
1046+
}
1047+
else {
1048+
previousSpanInfo = spanInfo;
1049+
length++;
1050+
}
9951051
}
1052+
addSpanInfoString();
9961053
return resultString;
1054+
1055+
function repeatString(count: number, char: string) {
1056+
var result = "";
1057+
for (var i = 0; i < count; i++) {
1058+
result += char;
1059+
}
1060+
return result;
1061+
}
1062+
}
1063+
1064+
public getBreakpointStatementLocation(pos: number) {
1065+
this.taoInvalidReason = 'getBreakpointStatementLocation NYI';
1066+
return this.languageService.getBreakpointStatementAtPosition(this.activeFile.fileName, pos);
9971067
}
9981068

9991069
public baselineCurrentFileBreakpointLocations() {
@@ -1003,12 +1073,7 @@ module FourSlash {
10031073
"Breakpoint Locations for " + this.activeFile.fileName,
10041074
this.testData.globalOptions[testOptMetadataNames.baselineFile],
10051075
() => {
1006-
var fileLength = this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName).getLength();
1007-
var resultString = "";
1008-
for (var pos = 0; pos < fileLength; pos++) {
1009-
resultString = resultString + this.getBreakpointStatementLocation(pos);
1010-
}
1011-
return resultString;
1076+
return this.baselineCurrentFileLocations(pos => this.getBreakpointStatementLocation(pos));
10121077
},
10131078
true /* run immediately */);
10141079
}
@@ -1056,7 +1121,7 @@ module FourSlash {
10561121
}
10571122

10581123
public printBreakpointLocation(pos: number) {
1059-
Harness.IO.log(this.getBreakpointStatementLocation(pos));
1124+
Harness.IO.log("\n**Pos: " + pos + " " + this.spanInfoToString(pos, this.getBreakpointStatementLocation(pos), " "));
10601125
}
10611126

10621127
public printBreakpointAtCurrentLocation() {
@@ -1502,7 +1567,7 @@ module FourSlash {
15021567
throw new Error('verifyCaretAtMarker failed - expected to be in file "' + pos.fileName + '", but was in file "' + this.activeFile.fileName + '"');
15031568
}
15041569
if (pos.position !== this.currentCaretPosition) {
1505-
throw new Error('verifyCaretAtMarker failed - expected to be at marker "/*' + markerName + '*/, but was at position ' + this.currentCaretPosition + '(' + this.getLineColStringAtCaret() + ')');
1570+
throw new Error('verifyCaretAtMarker failed - expected to be at marker "/*' + markerName + '*/, but was at position ' + this.currentCaretPosition + '(' + this.getLineColStringAtPosition(this.currentCaretPosition) + ')');
15061571
}
15071572
}
15081573

@@ -1566,10 +1631,10 @@ module FourSlash {
15661631
this.taoInvalidReason = 'verifyCurrentNameOrDottedNameSpanText NYI';
15671632

15681633
var span = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition);
1569-
if (span === null) {
1634+
if (!span) {
15701635
this.raiseError('verifyCurrentNameOrDottedNameSpanText\n' +
15711636
'\tExpected: "' + text + '"\n' +
1572-
'\t Actual: null');
1637+
'\t Actual: undefined');
15731638
}
15741639

15751640
var actual = this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName).getText(span.start(), span.end());
@@ -1581,12 +1646,8 @@ module FourSlash {
15811646
}
15821647

15831648
private getNameOrDottedNameSpan(pos: number) {
1584-
var spanInfo = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, pos, pos);
1585-
var resultString = "\n**Pos: " + pos + " SpanInfo: " + JSON.stringify(spanInfo) + "\n** Statement: ";
1586-
if (spanInfo !== null) {
1587-
resultString = resultString + this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName).getText(spanInfo.start(), spanInfo.end());
1588-
}
1589-
return resultString;
1649+
this.taoInvalidReason = 'getNameOrDottedNameSpan NYI';
1650+
return this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, pos, pos);
15901651
}
15911652

15921653
public baselineCurrentFileNameOrDottedNameSpans() {
@@ -1596,18 +1657,14 @@ module FourSlash {
15961657
"Name OrDottedNameSpans for " + this.activeFile.fileName,
15971658
this.testData.globalOptions[testOptMetadataNames.baselineFile],
15981659
() => {
1599-
var fileLength = this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName).getLength();
1600-
var resultString = "";
1601-
for (var pos = 0; pos < fileLength; pos++) {
1602-
resultString = resultString + this.getNameOrDottedNameSpan(pos);
1603-
}
1604-
return resultString;
1660+
return this.baselineCurrentFileLocations(pos =>
1661+
this.getNameOrDottedNameSpan(pos));
16051662
},
16061663
true /* run immediately */);
16071664
}
16081665

16091666
public printNameOrDottedNameSpans(pos: number) {
1610-
Harness.IO.log(this.getNameOrDottedNameSpan(pos));
1667+
Harness.IO.log(this.spanInfoToString(pos, this.getNameOrDottedNameSpan(pos), "**"));
16111668
}
16121669

16131670
private verifyClassifications(expected: { classificationType: string; text: string; textSpan?: TextSpan }[], actual: ts.ClassifiedSpan[]) {
@@ -2114,8 +2171,8 @@ module FourSlash {
21142171
return this.languageServiceShimHost.positionToZeroBasedLineCol(this.activeFile.fileName, this.currentCaretPosition).line + 1;
21152172
}
21162173

2117-
private getLineColStringAtCaret() {
2118-
var pos = this.languageServiceShimHost.positionToZeroBasedLineCol(this.activeFile.fileName, this.currentCaretPosition);
2174+
private getLineColStringAtPosition(position: number) {
2175+
var pos = this.languageServiceShimHost.positionToZeroBasedLineCol(this.activeFile.fileName, position);
21192176
return 'line ' + (pos.line + 1) + ', col ' + pos.character;
21202177
}
21212178

0 commit comments

Comments
 (0)