diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts
index fd91c7c70ec..26f86a02c38 100644
--- a/src/harness/fourslash.ts
+++ b/src/harness/fourslash.ts
@@ -732,22 +732,22 @@ module FourSlash {
this.taoInvalidReason = 'verifyCurrentSignatureHelpIs NYI';
var help = this.getActiveSignatureHelp();
- assert.equal(help.signatureInfo, expected);
+ assert.equal(help.prefix + help.parameters.map(p => p.display).join(help.separator) + help.suffix, expected);
}
public verifyCurrentParameterIsVariable(isVariable: boolean) {
this.taoInvalidReason = 'verifyCurrentParameterIsVariable NYI';
- var activeParameter = this.getActiveParameter();
- assert.isNotNull(activeParameter.parameter);
- assert.equal(isVariable, activeParameter.parameter.isVariable);
+ var signature = this.getActiveSignatureHelp();
+ assert.isNotNull(signature);
+ assert.equal(isVariable, signature.isVariadic);
}
public verifyCurrentParameterHelpName(name: string) {
this.taoInvalidReason = 'verifyCurrentParameterHelpName NYI';
var activeParameter = this.getActiveParameter();
- var activeParameterName = activeParameter.parameter ? activeParameter.parameter.name : activeParameter.typeParameter.name;
+ var activeParameterName = activeParameter.name;
assert.equal(activeParameterName, name);
}
@@ -756,16 +756,14 @@ module FourSlash {
var activeSignature = this.getActiveSignatureHelp();
var activeParameter = this.getActiveParameter();
- var activeParameterMinChar = activeParameter.parameter ? activeParameter.parameter.minChar : activeParameter.typeParameter.minChar;
- var activeParameterLimChar = activeParameter.parameter ? activeParameter.parameter.limChar : activeParameter.typeParameter.limChar;
- assert.equal(activeSignature.signatureInfo.substring(activeParameterMinChar, activeParameterLimChar), parameter);
+ assert.equal(activeParameter.display, parameter);
}
public verifyCurrentParameterHelpDocComment(docComment: string) {
this.taoInvalidReason = 'verifyCurrentParameterHelpDocComment NYI';
var activeParameter = this.getActiveParameter();
- var activeParameterDocComment = activeParameter.parameter ? activeParameter.parameter.docComment : activeParameter.typeParameter.docComment;
+ var activeParameterDocComment = activeParameter.documentation;
assert.equal(activeParameterDocComment, docComment);
}
@@ -778,13 +776,13 @@ module FourSlash {
public verifyCurrentSignatureHelpTypeParameterCount(expectedCount: number) {
this.taoInvalidReason = 'verifyCurrentSignatureHelpTypeParameterCount NYI';
- assert.equal(this.getActiveSignatureHelp().typeParameters.length, expectedCount);
+ // assert.equal(this.getActiveSignatureHelp().typeParameters.length, expectedCount);
}
public verifyCurrentSignatureHelpDocComment(docComment: string) {
this.taoInvalidReason = 'verifyCurrentSignatureHelpDocComment NYI';
- var actualDocComment = this.getActiveSignatureHelp().docComment;
+ var actualDocComment = this.getActiveSignatureHelp().documentation;
assert.equal(actualDocComment, docComment);
}
@@ -792,15 +790,15 @@ module FourSlash {
this.scenarioActions.push('');
this.scenarioActions.push('');
- var help = this.languageService.getSignatureAtPosition(this.activeFile.fileName, this.currentCaretPosition);
- var actual = help && help.formal ? help.formal.length : 0;
+ var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
+ var actual = help && help.items ? help.items.length : 0;
assert.equal(actual, expected);
}
public verifySignatureHelpPresent(shouldBePresent = true) {
this.taoInvalidReason = 'verifySignatureHelpPresent NYI';
- var actual = this.languageService.getSignatureAtPosition(this.activeFile.fileName, this.currentCaretPosition);
+ var actual = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
if (shouldBePresent) {
if (!actual) {
throw new Error("Expected signature help to be present, but it wasn't");
@@ -812,45 +810,32 @@ module FourSlash {
}
}
- private getFormalParameter() {
- var help = this.languageService.getSignatureAtPosition(this.activeFile.fileName, this.currentCaretPosition);
- return help.formal;
- }
+ //private getFormalParameter() {
+ // var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
+ // return help.formal;
+ //}
private getActiveSignatureHelp() {
- var help = this.languageService.getSignatureAtPosition(this.activeFile.fileName, this.currentCaretPosition);
- var activeFormal = help.activeFormal;
+ var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
// If the signature hasn't been narrowed down yet (e.g. no parameters have yet been entered),
// 'activeFormal' will be -1 (even if there is only 1 signature). Signature help will show the
// first signature in the signature group, so go with that
- if (activeFormal === -1) {
- activeFormal = 0;
- }
+ var index = help.selectedItemIndex < 0 ? 0 : help.selectedItemIndex;
- return help.formal[activeFormal];
+ return help.items[index];
}
- private getActiveParameter(): { parameter: ts.FormalParameterInfo; typeParameter: ts.FormalTypeParameterInfo; } {
+ private getActiveParameter(): ts.SignatureHelpParameter {
var currentSig = this.getActiveSignatureHelp();
- var help = this.languageService.getSignatureAtPosition(this.activeFile.fileName, this.currentCaretPosition);
+ var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
+
+ var item = help.items[help.selectedItemIndex];
+ var state = this.languageService.getSignatureHelpCurrentArgumentState(this.activeFile.fileName, this.currentCaretPosition, help.applicableSpan.start());
// Same logic as in getActiveSignatureHelp - this value might be -1 until a parameter value actually gets typed
- var currentParam = help.actual.currentParameter;
- if (currentParam === -1) currentParam = 0;
-
- if (help.actual.currentParameterIsTypeParameter) {
- return {
- parameter: null,
- typeParameter: currentSig.typeParameters[currentParam]
- };
- }
- else {
- return {
- parameter: currentSig.parameters[currentParam],
- typeParameter: null
- };
- }
+ var currentParam = state === null ? 0 : state.argumentIndex;
+ return item.parameters[currentParam];
}
public getBreakpointStatementLocation(pos: number) {
@@ -859,7 +844,7 @@ module FourSlash {
var spanInfo = this.languageService.getBreakpointStatementAtPosition(this.activeFile.fileName, pos);
var resultString = "\n**Pos: " + pos + " SpanInfo: " + JSON.stringify(spanInfo) + "\n** Statement: ";
if (spanInfo !== null) {
- resultString = resultString + this.activeFile.content.substr(spanInfo.minChar, spanInfo.limChar - spanInfo.minChar);
+ resultString = resultString + this.activeFile.content.substr(spanInfo.start(), spanInfo.length());
}
return resultString;
}
@@ -890,7 +875,7 @@ module FourSlash {
}
public printCurrentParameterHelp() {
- var help = this.languageService.getSignatureAtPosition(this.activeFile.fileName, this.currentCaretPosition);
+ var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
Harness.IO.log(JSON.stringify(help));
}
@@ -1071,7 +1056,7 @@ module FourSlash {
if (ch === '(' || ch === ',') {
/* Signature help*/
- this.languageService.getSignatureAtPosition(this.activeFile.fileName, offset);
+ this.languageService.getSignatureHelpItems(this.activeFile.fileName, offset);
} else if (prevChar === ' ' && /A-Za-z_/.test(ch)) {
/* Completions */
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset, false);
@@ -1111,7 +1096,7 @@ module FourSlash {
// Handle formatting
if (this.enableFormatting) {
- var edits = this.languageService.getFormattingEditsOnPaste(this.activeFile.fileName, start, offset, this.formatCodeOptions);
+ var edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions);
offset += this.applyEdits(this.activeFile.fileName, edits, true);
this.editCheckpoint(this.activeFile.fileName);
}
@@ -1175,18 +1160,18 @@ module FourSlash {
};
}
- private applyEdits(fileName: string, edits: ts.TextEdit[], isFormattingEdit = false): number {
+ private applyEdits(fileName: string, edits: ts.TextChange[], isFormattingEdit = false): number {
// We get back a set of edits, but langSvc.editScript only accepts one at a time. Use this to keep track
// of the incremental offest from each edit to the next. Assumption is that these edit ranges don't overlap
var runningOffset = 0;
- edits = edits.sort((a, b) => a.minChar - b.minChar);
+ edits = edits.sort((a, b) => a.span.start() - b.span.start());
// Get a snapshot of the content of the file so we can make sure any formatting edits didn't destroy non-whitespace characters
var snapshot = this.languageServiceShimHost.getScriptSnapshot(fileName);
var oldContent = snapshot.getText(0, snapshot.getLength());
for (var j = 0; j < edits.length; j++) {
- this.languageServiceShimHost.editScript(fileName, edits[j].minChar + runningOffset, edits[j].limChar + runningOffset, edits[j].text);
- this.updateMarkersForEdit(fileName, edits[j].minChar + runningOffset, edits[j].limChar + runningOffset, edits[j].text);
- var change = (edits[j].minChar - edits[j].limChar) + edits[j].text.length;
+ this.languageServiceShimHost.editScript(fileName, edits[j].span.start() + runningOffset, edits[j].span.end() + runningOffset, edits[j].newText);
+ this.updateMarkersForEdit(fileName, edits[j].span.start() + runningOffset, edits[j].span.end() + runningOffset, edits[j].newText);
+ var change = (edits[j].span.start() - edits[j].span.end()) + edits[j].newText.length;
runningOffset += change;
// TODO: Consider doing this at least some of the time for higher fidelity. Currently causes a failure (bug 707150)
// this.languageService.getScriptLexicalStructure(fileName);
@@ -1206,7 +1191,7 @@ module FourSlash {
public formatDocument() {
this.scenarioActions.push('');
- var edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, 0, this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName).getLength(), this.formatCodeOptions);
+ var edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeOptions);
this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, true);
this.fixCaretPosition();
}
@@ -1263,7 +1248,7 @@ module FourSlash {
var definition = definitions[definitionIndex];
this.openFile(definition.fileName);
- this.currentCaretPosition = definition.minChar;
+ this.currentCaretPosition = definition.textSpan.start();
}
public verifyDefinitionLocationExists(negative: boolean) {
@@ -1369,7 +1354,7 @@ module FourSlash {
'\t Actual: null');
}
- var actual = this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName).getText(span.minChar, span.limChar);
+ var actual = this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName).getText(span.start(), span.end());
if (actual !== text) {
throw new Error('verifyCurrentNameOrDottedNameSpanText\n' +
'\tExpected: "' + text + '"\n' +
@@ -1381,7 +1366,7 @@ module FourSlash {
var spanInfo = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, pos, pos);
var resultString = "\n**Pos: " + pos + " SpanInfo: " + JSON.stringify(spanInfo) + "\n** Statement: ";
if (spanInfo !== null) {
- resultString = resultString + this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName).getText(spanInfo.minChar, spanInfo.limChar);
+ resultString = resultString + this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName).getText(spanInfo.start(), spanInfo.end());
}
return resultString;
}
@@ -1410,7 +1395,7 @@ module FourSlash {
public verifyOutliningSpans(spans: TextSpan[]) {
this.taoInvalidReason = 'verifyOutliningSpans NYI';
- var actual = this.languageService.getOutliningRegions(this.activeFile.fileName);
+ var actual = this.languageService.getOutliningSpans(this.activeFile.fileName);
if (actual.length !== spans.length) {
throw new Error('verifyOutliningSpans failed - expected total spans to be ' + spans.length + ', but was ' + actual.length);
@@ -1584,70 +1569,61 @@ module FourSlash {
public verifyGetScriptLexicalStructureListCount(expected: number) {
this.taoInvalidReason = 'verifyNavigationItemsListContains impossible';
- var items = this.languageService.getScriptLexicalStructure(this.activeFile.fileName);
- var actual = (items && items.length) || 0;
+ var items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
+ var actual = this.getNavigationBarItemsCount(items);
+
if (expected != actual) {
throw new Error('verifyGetScriptLexicalStructureListCount failed - found: ' + actual + ' navigation items, expected: ' + expected + '.');
}
}
+ private getNavigationBarItemsCount(items: ts.NavigationBarItem[]) {
+ var result = 0;
+ if (items) {
+ for (var i = 0, n = items.length; i < n; i++) {
+ result++;
+ result += this.getNavigationBarItemsCount(items[i].childItems);
+ }
+ }
+
+ return result;
+ }
+
public verifGetScriptLexicalStructureListContains(
name: string,
kind: string,
- fileName?: string,
- parentName?: string,
- isAdditionalSpan?: boolean,
markerPosition?: number) {
this.taoInvalidReason = 'verifGetScriptLexicalStructureListContains impossible';
- var items = this.languageService.getScriptLexicalStructure(this.activeFile.fileName);
+ var items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
if (!items || items.length === 0) {
throw new Error('verifyGetScriptLexicalStructureListContains failed - found 0 navigation items, expected at least one.');
}
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- if (item && item.name === name && item.kind === kind &&
- (fileName === undefined || item.fileName === fileName) &&
- (parentName === undefined || item.containerName === parentName)) {
- if (markerPosition !== undefined || isAdditionalSpan !== undefined) {
- if (isAdditionalSpan) {
- if (item.additionalSpans &&
- item.additionalSpans.some(span => span.minChar <= markerPosition && markerPosition <= span.limChar)) {
- // marker is in an additional span for this item.
- return;
- }
- else {
- throw new Error(
- 'verifGetScriptLexicalStructureListContains failed - ' +
- 'no additional span was found that contained the position: ' + JSON.stringify(markerPosition) +
- ' in the item: ' + JSON.stringify(item));
- }
- }
- else if (!isAdditionalSpan) {
- if (item.minChar <= markerPosition &&
- markerPosition <= item.minChar) {
- // marker is in span normal item's span
- return;
- }
- else {
- throw new Error(
- 'verifGetScriptLexicalStructureListContains failed - ' +
- 'marker was positioned: ' + JSON.stringify(markerPosition) +
- ' which is not in the item: ' + JSON.stringify(item));
- }
- }
+ if (this.navigationBarItemsContains(items, name, kind)) {
+ return;
+ }
+
+ var missingItem = { name: name, kind: kind };
+ throw new Error('verifyGetScriptLexicalStructureListContains failed - could not find the item: ' + JSON.stringify(missingItem) + ' in the returned list: (' + JSON.stringify(items) + ')');
+ }
+
+ private navigationBarItemsContains(items: ts.NavigationBarItem[], name: string, kind: string) {
+ if (items) {
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ if (item && item.text === name && item.kind === kind) {
+ return true;
}
- else {
- return;
+
+ if (this.navigationBarItemsContains(item.childItems, name, kind)) {
+ return true;
}
}
}
-
- var missingItem = { name: name, kind: kind, fileName: fileName, parentName: parentName };
- throw new Error('verifyGetScriptLexicalStructureListContains failed - could not find the item: ' + JSON.stringify(missingItem) + ' in the returned list: (' + JSON.stringify(items) + ')');
+ return false;
}
public printNavigationItems(searchValue: string) {
@@ -1663,14 +1639,14 @@ module FourSlash {
}
public printScriptLexicalStructureItems() {
- var items = this.languageService.getScriptLexicalStructure(this.activeFile.fileName);
+ var items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
var length = items && items.length;
Harness.IO.log('NavigationItems list (' + length + ' items)');
for (var i = 0; i < length; i++) {
var item = items[i];
- Harness.IO.log('name: ' + item.name + ', kind: ' + item.kind + ', parentName: ' + item.containerName + ', fileName: ' + item.fileName);
+ Harness.IO.log('name: ' + item.text + ', kind: ' + item.kind);
}
}
@@ -1689,7 +1665,7 @@ module FourSlash {
for (var i = 0; i < occurances.length; i++) {
var occurance = occurances[i];
- if (occurance && occurance.fileName === fileName && occurance.minChar === start && occurance.limChar === end) {
+ if (occurance && occurance.fileName === fileName && occurance.textSpan.start() === start && occurance.textSpan.end() === end) {
if (typeof isWriteAccess !== "undefined" && occurance.isWriteAccess !== isWriteAccess) {
throw new Error('verifyOccurancesAtPositionListContains failed - item isWriteAccess value doe not match, actual: ' + occurance.isWriteAccess + ', expected: ' + isWriteAccess + '.');
}
diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts
index 0f904b24a17..48f2f9b9653 100644
--- a/src/harness/harnessLanguageService.ts
+++ b/src/harness/harnessLanguageService.ts
@@ -281,7 +281,7 @@ module Harness.LanguageService {
}
/** Verify that applying edits to sourceFileName result in the content of the file baselineFileName */
- public checkEdits(sourceFileName: string, baselineFileName: string, edits: ts.TextEdit[]) {
+ public checkEdits(sourceFileName: string, baselineFileName: string, edits: ts.TextChange[]) {
var script = Harness.IO.readFile(sourceFileName);
var formattedScript = this.applyEdits(script, edits);
var baseline = Harness.IO.readFile(baselineFileName);
@@ -310,26 +310,26 @@ module Harness.LanguageService {
/** Apply an array of text edits to a string, and return the resulting string. */
- public applyEdits(content: string, edits: ts.TextEdit[]): string {
+ public applyEdits(content: string, edits: ts.TextChange[]): string {
var result = content;
edits = this.normalizeEdits(edits);
for (var i = edits.length - 1; i >= 0; i--) {
var edit = edits[i];
- var prefix = result.substring(0, edit.minChar);
- var middle = edit.text;
- var suffix = result.substring(edit.limChar);
+ var prefix = result.substring(0, edit.span.start());
+ var middle = edit.newText;
+ var suffix = result.substring(edit.span.end());
result = prefix + middle + suffix;
}
return result;
}
/** Normalize an array of edits by removing overlapping entries and sorting entries on the minChar position. */
- private normalizeEdits(edits: ts.TextEdit[]): ts.TextEdit[] {
- var result: ts.TextEdit[] = [];
+ private normalizeEdits(edits: ts.TextChange[]): ts.TextChange[] {
+ var result: ts.TextChange[] = [];
- function mapEdits(edits: ts.TextEdit[]): { edit: ts.TextEdit; index: number; }[] {
- var result: { edit: ts.TextEdit; index: number; }[] = [];
+ function mapEdits(edits: ts.TextChange[]): { edit: ts.TextChange; index: number; }[] {
+ var result: { edit: ts.TextChange; index: number; }[] = [];
for (var i = 0; i < edits.length; i++) {
result.push({ edit: edits[i], index: i });
}
@@ -337,7 +337,7 @@ module Harness.LanguageService {
}
var temp = mapEdits(edits).sort(function (a, b) {
- var result = a.edit.minChar - b.edit.limChar;
+ var result = a.edit.span.start() - b.edit.span.start();
if (result === 0)
result = a.index - b.index;
return result;
@@ -356,7 +356,7 @@ module Harness.LanguageService {
}
var nextEdit = temp[next].edit;
- var gap = nextEdit.minChar - currentEdit.limChar;
+ var gap = nextEdit.span.start() - currentEdit.span.end();
// non-overlapping edits
if (gap >= 0) {
@@ -365,10 +365,10 @@ module Harness.LanguageService {
next++;
continue;
}
-
+
// overlapping edits: for now, we only support ignoring an next edit
// entirely contained in the current edit.
- if (currentEdit.minChar >= nextEdit.limChar) {
+ if (currentEdit.span.end() >= nextEdit.span.end()) {
next++;
continue;
}
diff --git a/src/services/braceMatcher.ts b/src/services/braceMatcher.ts
index 96550dab2e7..3615f677024 100644
--- a/src/services/braceMatcher.ts
+++ b/src/services/braceMatcher.ts
@@ -24,93 +24,50 @@ module TypeScript.Services {
public static getMatchSpans(syntaxTree: TypeScript.SyntaxTree, position: number): TypeScript.TextSpan[] {
var result: TypeScript.TextSpan[] = [];
- var currentToken = findToken(syntaxTree.sourceUnit(), position);
+ var token = findToken(syntaxTree.sourceUnit(), position);
- BraceMatcher.getMatchingCloseBrace(currentToken, position, result);
- BraceMatcher.getMatchingOpenBrace(currentToken, position, result);
+ if (start(token) === position) {
+ var matchKind = BraceMatcher.getMatchingTokenKind(token);
+
+ if (matchKind !== null) {
+ var parentElement = token.parent;
+
+ for (var i = 0, n = childCount(parentElement); i < n; i++) {
+ var current = childAt(parentElement, i);
+
+ if (current !== null && fullWidth(current) > 0) {
+ if (current.kind() === matchKind) {
+ var range1 = new TypeScript.TextSpan(start(token), width(token));
+ var range2 = new TypeScript.TextSpan(start(current), width(current));
+ if (range1.start() < range2.start()) {
+ result.push(range1, range2);
+ }
+ else {
+ result.push(range2, range1);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
return result;
}
- private static getMatchingCloseBrace(currentToken: TypeScript.ISyntaxToken, position: number, result: TypeScript.TextSpan[]) {
- if (start(currentToken) === position) {
- var closingBraceKind = BraceMatcher.getMatchingCloseBraceTokenKind(currentToken);
- if (closingBraceKind !== null) {
- var parentElement = currentToken.parent;
- var currentPosition = fullStart(currentToken.parent);
- for (var i = 0, n = childCount(parentElement); i < n; i++) {
- var element = childAt(parentElement, i);
- if (element !== null && fullWidth(element) > 0) {
- if (element.kind() === closingBraceKind) {
- var range1 = new TypeScript.TextSpan(position, width(currentToken));
- var range2 = new TypeScript.TextSpan(currentPosition + leadingTriviaWidth(element), width(element));
- result.push(range1, range2);
- break;
- }
-
- currentPosition += fullWidth(element);
- }
- }
- }
- }
- }
-
- private static getMatchingOpenBrace(currentToken: TypeScript.ISyntaxToken, position: number, result: TypeScript.TextSpan[]) {
- // Check if the current token to the left is a close brace
- if (currentToken.fullStart() === position) {
- currentToken = previousToken(currentToken);
+ private static getMatchingTokenKind(token: TypeScript.ISyntaxToken): TypeScript.SyntaxKind {
+ switch (token.kind()) {
+ case TypeScript.SyntaxKind.OpenBraceToken: return TypeScript.SyntaxKind.CloseBraceToken
+ case TypeScript.SyntaxKind.OpenParenToken: return TypeScript.SyntaxKind.CloseParenToken;
+ case TypeScript.SyntaxKind.OpenBracketToken: return TypeScript.SyntaxKind.CloseBracketToken;
+ case TypeScript.SyntaxKind.LessThanToken: return TypeScript.SyntaxKind.GreaterThanToken;
+ case TypeScript.SyntaxKind.CloseBraceToken: return TypeScript.SyntaxKind.OpenBraceToken
+ case TypeScript.SyntaxKind.CloseParenToken: return TypeScript.SyntaxKind.OpenParenToken;
+ case TypeScript.SyntaxKind.CloseBracketToken: return TypeScript.SyntaxKind.OpenBracketToken;
+ case TypeScript.SyntaxKind.GreaterThanToken: return TypeScript.SyntaxKind.LessThanToken;
}
- if (currentToken !== null && start(currentToken) === (position - 1)) {
- var openBraceKind = BraceMatcher.getMatchingOpenBraceTokenKind(currentToken);
- if (openBraceKind !== null) {
- var parentElement = currentToken.parent;
- var currentPosition = fullStart(currentToken.parent) + fullWidth(parentElement);
- for (var i = childCount(parentElement) - 1 ; i >= 0; i--) {
- var element = childAt(parentElement, i);
- if (element !== null && fullWidth(element) > 0) {
- if (element.kind() === openBraceKind) {
- var range1 = new TypeScript.TextSpan(position - 1, width(currentToken));
- var range2 = new TypeScript.TextSpan(currentPosition - lastToken(element).trailingTriviaWidth() - width(element), width(element));
- result.push(range1, range2);
- break;
- }
-
- currentPosition -= fullWidth(element);
- }
- }
- }
- }
- }
-
- private static getMatchingCloseBraceTokenKind(positionedElement: TypeScript.ISyntaxElement): TypeScript.SyntaxKind {
- var element = positionedElement !== null && positionedElement;
- switch (element.kind()) {
- case TypeScript.SyntaxKind.OpenBraceToken:
- return TypeScript.SyntaxKind.CloseBraceToken;
- case TypeScript.SyntaxKind.OpenParenToken:
- return TypeScript.SyntaxKind.CloseParenToken;
- case TypeScript.SyntaxKind.OpenBracketToken:
- return TypeScript.SyntaxKind.CloseBracketToken;
- case TypeScript.SyntaxKind.LessThanToken:
- return TypeScript.SyntaxUtilities.isAngleBracket(positionedElement) ? TypeScript.SyntaxKind.GreaterThanToken : null;
- }
- return null;
- }
-
- private static getMatchingOpenBraceTokenKind(positionedElement: TypeScript.ISyntaxElement): TypeScript.SyntaxKind {
- var element = positionedElement !== null && positionedElement;
- switch (element.kind()) {
- case TypeScript.SyntaxKind.CloseBraceToken:
- return TypeScript.SyntaxKind.OpenBraceToken
- case TypeScript.SyntaxKind.CloseParenToken:
- return TypeScript.SyntaxKind.OpenParenToken;
- case TypeScript.SyntaxKind.CloseBracketToken:
- return TypeScript.SyntaxKind.OpenBracketToken;
- case TypeScript.SyntaxKind.GreaterThanToken:
- return TypeScript.SyntaxUtilities.isAngleBracket(positionedElement) ? TypeScript.SyntaxKind.LessThanToken : null;
- }
return null;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts
index 5dd057ac2af..12de22d3bd0 100644
--- a/src/services/breakpoints.ts
+++ b/src/services/breakpoints.ts
@@ -4,16 +4,13 @@
///
module TypeScript.Services.Breakpoints {
- function createBreakpointSpanInfo(parentElement: TypeScript.ISyntaxElement, ...childElements: TypeScript.ISyntaxElement[]): ts.SpanInfo {
+ function createBreakpointSpanInfo(parentElement: TypeScript.ISyntaxElement, ...childElements: TypeScript.ISyntaxElement[]): TextSpan {
if (!parentElement) {
return null;
}
if (childElements.length == 0) {
- return {
- minChar: TypeScript.start(parentElement),
- limChar: TypeScript.end(parentElement)
- };
+ return TextSpan.fromBounds(TypeScript.start(parentElement), TypeScript.end(parentElement));
}
var start: number;
@@ -28,24 +25,18 @@ module TypeScript.Services.Breakpoints {
}
}
- return {
- minChar: start,
- limChar: end
- };
+ return TextSpan.fromBounds(start, end);
}
- function createBreakpointSpanInfoWithLimChar(startElement: TypeScript.ISyntaxElement, limChar: number): ts.SpanInfo {
- return {
- minChar: start(startElement),
- limChar: limChar
- };
+ function createBreakpointSpanInfoWithLimChar(startElement: TypeScript.ISyntaxElement, limChar: number): TextSpan {
+ return TextSpan.fromBounds(start(startElement), limChar);
}
class BreakpointResolver {
constructor(private posLine: number, private lineMap: TypeScript.LineMap) {
}
- private breakpointSpanOfToken(positionedToken: TypeScript.ISyntaxToken): ts.SpanInfo {
+ private breakpointSpanOfToken(positionedToken: TypeScript.ISyntaxToken): TextSpan {
switch (positionedToken.kind()) {
case TypeScript.SyntaxKind.OpenBraceToken:
return this.breakpointSpanOfOpenBrace(positionedToken);
@@ -74,7 +65,7 @@ module TypeScript.Services.Breakpoints {
return this.breakpointSpanOfContainingNode(positionedToken);
}
- private breakpointSpanOfOpenBrace(openBraceToken: TypeScript.ISyntaxToken): ts.SpanInfo {
+ private breakpointSpanOfOpenBrace(openBraceToken: TypeScript.ISyntaxToken): TextSpan {
var container = Syntax.containingNode(openBraceToken);
if (container) {
var originalContainer = container;
@@ -168,7 +159,7 @@ module TypeScript.Services.Breakpoints {
return null;
}
- private breakpointSpanOfCloseBrace(closeBraceToken: TypeScript.ISyntaxToken): ts.SpanInfo {
+ private breakpointSpanOfCloseBrace(closeBraceToken: TypeScript.ISyntaxToken): TextSpan {
var container = Syntax.containingNode(closeBraceToken);
if (container) {
var originalContainer = container;
@@ -243,7 +234,7 @@ module TypeScript.Services.Breakpoints {
}
- private breakpointSpanOfComma(commaToken: TypeScript.ISyntaxToken): ts.SpanInfo {
+ private breakpointSpanOfComma(commaToken: TypeScript.ISyntaxToken): TextSpan {
var commaParent = commaToken.parent;
if (isSeparatedList(commaParent)) {
var grandParent = commaParent.parent;
@@ -271,7 +262,7 @@ module TypeScript.Services.Breakpoints {
return this.breakpointSpanOfContainingNode(commaToken);
}
- private breakpointSpanOfCloseParen(closeParenToken: TypeScript.ISyntaxToken): ts.SpanInfo {
+ private breakpointSpanOfCloseParen(closeParenToken: TypeScript.ISyntaxToken): TextSpan {
var closeParenParent = closeParenToken.parent;
if (closeParenParent) {
switch (closeParenParent.kind()) {
@@ -293,7 +284,7 @@ module TypeScript.Services.Breakpoints {
return blockSyntax.statements && blockSyntax.statements.length != 0;
}
- private breakpointSpanOfFirstStatementInBlock(blockNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfFirstStatementInBlock(blockNode: TypeScript.ISyntaxNode): TextSpan {
if (!blockNode) {
return null;
}
@@ -316,7 +307,7 @@ module TypeScript.Services.Breakpoints {
}
}
- private breakpointSpanOfLastStatementInBlock(blockNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfLastStatementInBlock(blockNode: TypeScript.ISyntaxNode): TextSpan {
if (!blockNode) {
return null;
}
@@ -339,7 +330,7 @@ module TypeScript.Services.Breakpoints {
}
}
- private breakpointSpanOfFirstChildOfSyntaxList(positionedList: TypeScript.ISyntaxNodeOrToken[]): ts.SpanInfo {
+ private breakpointSpanOfFirstChildOfSyntaxList(positionedList: TypeScript.ISyntaxNodeOrToken[]): TextSpan {
if (!positionedList) {
return null;
}
@@ -363,7 +354,7 @@ module TypeScript.Services.Breakpoints {
}
}
- private breakpointSpanOfLastChildOfSyntaxList(positionedList: TypeScript.ISyntaxNodeOrToken[]): ts.SpanInfo {
+ private breakpointSpanOfLastChildOfSyntaxList(positionedList: TypeScript.ISyntaxNodeOrToken[]): TextSpan {
if (!positionedList) {
return null;
}
@@ -385,7 +376,7 @@ module TypeScript.Services.Breakpoints {
}
}
- private breakpointSpanOfNode(positionedNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfNode(positionedNode: ISyntaxNode): TextSpan {
var node = positionedNode;
switch (node.kind()) {
// Declarations with elements
@@ -493,7 +484,7 @@ module TypeScript.Services.Breakpoints {
}
return false;
}
-
+
private isInitializerOfForStatement(expressionNode: TypeScript.ISyntaxNode): boolean {
if (!expressionNode) {
return false;
@@ -552,12 +543,12 @@ module TypeScript.Services.Breakpoints {
return false;
}
- private breakpointOfLeftOfCommaExpression(commaExpressionNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointOfLeftOfCommaExpression(commaExpressionNode: TypeScript.ISyntaxNode): TextSpan {
var commaExpression = commaExpressionNode;
return this.breakpointSpanOf(commaExpression.left);
}
- private breakpointOfExpression(expressionNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointOfExpression(expressionNode: TypeScript.ISyntaxNode): TextSpan {
if (this.isInitializerOfForStatement(expressionNode) ||
this.isConditionOfForStatement(expressionNode) ||
this.isIncrememtorOfForStatement(expressionNode)) {
@@ -582,7 +573,7 @@ module TypeScript.Services.Breakpoints {
return this.breakpointSpanOfContainingNode(expressionNode);
}
- private breakpointSpanOfStatement(statementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfStatement(statementNode: TypeScript.ISyntaxNode): TextSpan {
var statement = statementNode;
if (statement.kind() == TypeScript.SyntaxKind.EmptyStatement) {
return null;
@@ -722,7 +713,7 @@ module TypeScript.Services.Breakpoints {
return positionedNode && !TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(positionedNode);
}
- private breakpointSpanOfDeclarationWithElements(positionedNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfDeclarationWithElements(positionedNode: TypeScript.ISyntaxNode): TextSpan {
if (!this.canHaveBreakpointInDeclaration(positionedNode)) {
return null;
}
@@ -751,7 +742,7 @@ module TypeScript.Services.Breakpoints {
return !!varDeclaratorSyntax.equalsValueClause;
}
- private breakpointSpanOfVariableDeclarator(varDeclaratorNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfVariableDeclarator(varDeclaratorNode: TypeScript.ISyntaxNode): TextSpan {
if (!this.canHaveBreakpointInVariableDeclarator(varDeclaratorNode)) {
return null;
}
@@ -799,7 +790,7 @@ module TypeScript.Services.Breakpoints {
return false;
}
- private breakpointSpanOfVariableDeclaration(varDeclarationNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfVariableDeclaration(varDeclarationNode: TypeScript.ISyntaxNode): TextSpan {
if (!this.canHaveBreakpointInDeclaration(varDeclarationNode)) {
return null;
}
@@ -830,7 +821,7 @@ module TypeScript.Services.Breakpoints {
return this.canHaveBreakpointInVariableDeclaration(variableStatement.variableDeclaration);
}
- private breakpointSpanOfVariableStatement(varStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfVariableStatement(varStatementNode: TypeScript.ISyntaxNode): TextSpan {
if (!this.canHaveBreakpointInVariableStatement(varStatementNode)) {
return null;
}
@@ -842,7 +833,7 @@ module TypeScript.Services.Breakpoints {
return createBreakpointSpanInfoWithLimChar(varStatementNode, end(childAt(varDeclarators, 0)));
}
- private breakpointSpanOfParameter(parameterNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfParameter(parameterNode: TypeScript.ISyntaxNode): TextSpan {
if (parameterNode.parent.kind() === SyntaxKind.SimpleArrowFunctionExpression) {
return this.breakpointSpanOfNode(parameterNode.parent);
}
@@ -860,7 +851,7 @@ module TypeScript.Services.Breakpoints {
}
}
- private breakpointSpanOfMemberVariableDeclaration(memberVarDeclarationNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfMemberVariableDeclaration(memberVarDeclarationNode: TypeScript.ISyntaxNode): TextSpan {
if (TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(memberVarDeclarationNode)) {
return null;
}
@@ -874,7 +865,7 @@ module TypeScript.Services.Breakpoints {
}
}
- private breakpointSpanOfImportDeclaration(importDeclarationNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfImportDeclaration(importDeclarationNode: TypeScript.ISyntaxNode): TextSpan {
if (TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(importDeclarationNode)) {
return null;
}
@@ -883,7 +874,7 @@ module TypeScript.Services.Breakpoints {
return createBreakpointSpanInfo(importDeclarationNode, importSyntax.modifiers, importSyntax.importKeyword, importSyntax.identifier, importSyntax.equalsToken, importSyntax.moduleReference);
}
- private breakpointSpanOfEnumDeclaration(enumDeclarationNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfEnumDeclaration(enumDeclarationNode: TypeScript.ISyntaxNode): TextSpan {
if (!this.canHaveBreakpointInDeclaration(enumDeclarationNode)) {
return null;
}
@@ -891,7 +882,7 @@ module TypeScript.Services.Breakpoints {
return createBreakpointSpanInfo(enumDeclarationNode);
}
- private breakpointSpanOfFirstEnumElement(enumDeclarationNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfFirstEnumElement(enumDeclarationNode: TypeScript.ISyntaxNode): TextSpan {
var enumDeclarationSyntax = enumDeclarationNode;
var enumElements = enumDeclarationSyntax.enumElements;
if (enumElements && childCount(enumElements)) {
@@ -901,7 +892,7 @@ module TypeScript.Services.Breakpoints {
return null;
}
- private breakpointSpanOfEnumElement(enumElementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfEnumElement(enumElementNode: TypeScript.ISyntaxNode): TextSpan {
if (TypeScript.SyntaxUtilities.isAmbientDeclarationSyntax(enumElementNode)) {
return null;
}
@@ -909,45 +900,45 @@ module TypeScript.Services.Breakpoints {
return createBreakpointSpanInfo(enumElementNode);
}
- private breakpointSpanOfIfStatement(ifStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfIfStatement(ifStatementNode: TypeScript.ISyntaxNode): TextSpan {
var ifStatement = ifStatementNode;
return createBreakpointSpanInfo(ifStatementNode, ifStatement.ifKeyword, ifStatement.openParenToken, ifStatement.condition, ifStatement.closeParenToken);
}
- private breakpointSpanOfElseClause(elseClauseNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfElseClause(elseClauseNode: TypeScript.ISyntaxNode): TextSpan {
var elseClause = elseClauseNode;
return this.breakpointSpanOf(elseClause.statement);
}
- private breakpointSpanOfForInStatement(forInStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfForInStatement(forInStatementNode: TypeScript.ISyntaxNode): TextSpan {
var forInStatement = forInStatementNode;
return createBreakpointSpanInfo(forInStatementNode, forInStatement.forKeyword, forInStatement.openParenToken, forInStatement.variableDeclaration,
forInStatement.left, forInStatement.inKeyword, forInStatement.expression, forInStatement.closeParenToken);
}
- private breakpointSpanOfForStatement(forStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfForStatement(forStatementNode: TypeScript.ISyntaxNode): TextSpan {
var forStatement = forStatementNode;
return this.breakpointSpanOf(forStatement.variableDeclaration
? forStatement.variableDeclaration
: forStatement.initializer);
}
- private breakpointSpanOfWhileStatement(whileStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfWhileStatement(whileStatementNode: TypeScript.ISyntaxNode): TextSpan {
var whileStatement = whileStatementNode;
return createBreakpointSpanInfo(whileStatementNode, whileStatement.whileKeyword, whileStatement.openParenToken, whileStatement.condition, whileStatement.closeParenToken);
}
- private breakpointSpanOfDoStatement(doStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfDoStatement(doStatementNode: TypeScript.ISyntaxNode): TextSpan {
var doStatement = doStatementNode;
return createBreakpointSpanInfo(doStatementNode, doStatement.whileKeyword, doStatement.openParenToken, doStatement.condition, doStatement.closeParenToken);
}
- private breakpointSpanOfSwitchStatement(switchStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfSwitchStatement(switchStatementNode: TypeScript.ISyntaxNode): TextSpan {
var switchStatement = switchStatementNode;
return createBreakpointSpanInfo(switchStatementNode, switchStatement.switchKeyword, switchStatement.openParenToken, switchStatement.expression, switchStatement.closeParenToken);
}
- private breakpointSpanOfFirstStatementOfFirstCaseClause(switchStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfFirstStatementOfFirstCaseClause(switchStatementNode: TypeScript.ISyntaxNode): TextSpan {
var switchStatement = switchStatementNode;
if (switchStatement.switchClauses && switchStatement.switchClauses.length == 0) {
return null;
@@ -964,7 +955,7 @@ module TypeScript.Services.Breakpoints {
return this.breakpointSpanOfFirstChildOfSyntaxList(statements);
}
- private breakpointSpanOfLastStatementOfLastCaseClause(switchStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfLastStatementOfLastCaseClause(switchStatementNode: TypeScript.ISyntaxNode): TextSpan {
var switchStatement = switchStatementNode;
if (switchStatement.switchClauses && switchStatement.switchClauses.length == 0) {
return null;
@@ -981,37 +972,37 @@ module TypeScript.Services.Breakpoints {
return this.breakpointSpanOfLastChildOfSyntaxList(statements);
}
- private breakpointSpanOfCaseSwitchClause(caseClauseNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfCaseSwitchClause(caseClauseNode: TypeScript.ISyntaxNode): TextSpan {
var caseSwitchClause = caseClauseNode;
return this.breakpointSpanOfFirstChildOfSyntaxList(caseSwitchClause.statements);
}
- private breakpointSpanOfDefaultSwitchClause(defaultSwithClauseNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfDefaultSwitchClause(defaultSwithClauseNode: TypeScript.ISyntaxNode): TextSpan {
var defaultSwitchClause = defaultSwithClauseNode;
return this.breakpointSpanOfFirstChildOfSyntaxList(defaultSwitchClause.statements);
}
- private breakpointSpanOfWithStatement(withStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfWithStatement(withStatementNode: TypeScript.ISyntaxNode): TextSpan {
var withStatement = withStatementNode;
return this.breakpointSpanOf(withStatement.statement);
}
- private breakpointSpanOfTryStatement(tryStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfTryStatement(tryStatementNode: TypeScript.ISyntaxNode): TextSpan {
var tryStatement = tryStatementNode;
return this.breakpointSpanOfFirstStatementInBlock(tryStatement.block);
}
- private breakpointSpanOfCatchClause(catchClauseNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfCatchClause(catchClauseNode: TypeScript.ISyntaxNode): TextSpan {
var catchClause = catchClauseNode;
return createBreakpointSpanInfo(catchClauseNode, catchClause.catchKeyword, catchClause.openParenToken, catchClause.identifier, catchClause.typeAnnotation, catchClause.closeParenToken);
}
- private breakpointSpanOfFinallyClause(finallyClauseNode: TypeScript.ISyntaxNode): ts.SpanInfo {
+ private breakpointSpanOfFinallyClause(finallyClauseNode: TypeScript.ISyntaxNode): TextSpan {
var finallyClause = finallyClauseNode;
return this.breakpointSpanOfFirstStatementInBlock(finallyClause.block);
}
- private breakpointSpanOfParenthesizedArrowFunctionExpression(arrowFunctionExpression: ParenthesizedArrowFunctionExpressionSyntax): ts.SpanInfo {
+ private breakpointSpanOfParenthesizedArrowFunctionExpression(arrowFunctionExpression: ParenthesizedArrowFunctionExpressionSyntax): TextSpan {
if (arrowFunctionExpression.block) {
return this.breakpointSpanOfFirstStatementInBlock(arrowFunctionExpression.block);
}
@@ -1020,7 +1011,7 @@ module TypeScript.Services.Breakpoints {
}
}
- private breakpointSpanOfSimpleArrowFunctionExpression(arrowFunctionExpression: SimpleArrowFunctionExpressionSyntax): ts.SpanInfo {
+ private breakpointSpanOfSimpleArrowFunctionExpression(arrowFunctionExpression: SimpleArrowFunctionExpressionSyntax): TextSpan {
if (arrowFunctionExpression.block) {
return this.breakpointSpanOfFirstStatementInBlock(arrowFunctionExpression.block);
}
@@ -1029,7 +1020,7 @@ module TypeScript.Services.Breakpoints {
}
}
- private breakpointSpanOfContainingNode(positionedElement: ISyntaxElement): ts.SpanInfo {
+ private breakpointSpanOfContainingNode(positionedElement: ISyntaxElement): TextSpan {
var current = positionedElement.parent;
while (!isNode(current)) {
current = current.parent;
@@ -1038,7 +1029,7 @@ module TypeScript.Services.Breakpoints {
return this.breakpointSpanOf(current);
}
- private breakpointSpanIfStartsOnSameLine(positionedElement: TypeScript.ISyntaxElement): ts.SpanInfo {
+ private breakpointSpanIfStartsOnSameLine(positionedElement: TypeScript.ISyntaxElement): TextSpan {
if (positionedElement && this.posLine == this.lineMap.getLineNumberFromPosition(start(positionedElement))) {
return this.breakpointSpanOf(positionedElement);
}
@@ -1046,7 +1037,7 @@ module TypeScript.Services.Breakpoints {
return null;
}
- public breakpointSpanOf(positionedElement: TypeScript.ISyntaxElement): ts.SpanInfo {
+ public breakpointSpanOf(positionedElement: TypeScript.ISyntaxElement): TextSpan {
if (!positionedElement) {
return null;
}
@@ -1075,7 +1066,7 @@ module TypeScript.Services.Breakpoints {
}
}
- export function getBreakpointLocation(syntaxTree: TypeScript.SyntaxTree, askedPos: number): ts.SpanInfo {
+ export function getBreakpointLocation(syntaxTree: TypeScript.SyntaxTree, askedPos: number): TextSpan {
// Cannot set breakpoint in dts file
if (TypeScript.isDTSFile(syntaxTree.fileName())) {
return null;
diff --git a/src/services/formatting/formattingManager.ts b/src/services/formatting/formattingManager.ts
index 57c854196a8..359f19c84ed 100644
--- a/src/services/formatting/formattingManager.ts
+++ b/src/services/formatting/formattingManager.ts
@@ -19,28 +19,26 @@ module TypeScript.Services.Formatting {
export class FormattingManager {
private options: FormattingOptions;
- constructor(private syntaxTree: SyntaxTree, private snapshot: ITextSnapshot, private rulesProvider: RulesProvider, editorOptions: ts.EditorOptions) {
+ constructor(private syntaxTree: SyntaxTree,
+ private snapshot: ITextSnapshot,
+ private rulesProvider: RulesProvider,
+ editorOptions: ts.EditorOptions) {
//
// TODO: convert to use FormattingOptions instead of EditorOptions
- this.options = new FormattingOptions(!editorOptions.ConvertTabsToSpaces, editorOptions.TabSize, editorOptions.IndentSize, editorOptions.NewLineCharacter);
+ this.options = new FormattingOptions(!editorOptions.ConvertTabsToSpaces, editorOptions.TabSize, editorOptions.IndentSize, editorOptions.NewLineCharacter)
}
- public formatSelection(minChar: number, limChar: number): ts.TextEdit[] {
+ public formatSelection(minChar: number, limChar: number): ts.TextChange[] {
var span = TextSpan.fromBounds(minChar, limChar);
return this.formatSpan(span, FormattingRequestKind.FormatSelection);
}
- public formatDocument(minChar: number, limChar: number): ts.TextEdit[] {
- var span = TextSpan.fromBounds(minChar, limChar);
+ public formatDocument(): ts.TextChange[] {
+ var span = TextSpan.fromBounds(0, this.snapshot.getLength());
return this.formatSpan(span, FormattingRequestKind.FormatDocument);
}
- public formatOnPaste(minChar: number, limChar: number): ts.TextEdit[] {
- var span = TextSpan.fromBounds(minChar, limChar);
- return this.formatSpan(span, FormattingRequestKind.FormatOnPaste);
- }
-
- public formatOnSemicolon(caretPosition: number): ts.TextEdit[] {
+ public formatOnSemicolon(caretPosition: number): ts.TextChange[] {
var sourceUnit = this.syntaxTree.sourceUnit();
var semicolonPositionedToken = findToken(sourceUnit, caretPosition - 1);
@@ -48,7 +46,7 @@ module TypeScript.Services.Formatting {
// Find the outer most parent that this semicolon terminates
var current: ISyntaxElement = semicolonPositionedToken;
while (current.parent !== null &&
- end(current.parent) === end(semicolonPositionedToken) &&
+ end(current.parent) === end(semicolonPositionedToken) &&
current.parent.kind() !== SyntaxKind.List) {
current = current.parent;
}
@@ -63,7 +61,7 @@ module TypeScript.Services.Formatting {
return [];
}
- public formatOnClosingCurlyBrace(caretPosition: number): ts.TextEdit[] {
+ public formatOnClosingCurlyBrace(caretPosition: number): ts.TextChange[] {
var sourceUnit = this.syntaxTree.sourceUnit();
var closeBracePositionedToken = findToken(sourceUnit, caretPosition - 1);
@@ -71,8 +69,8 @@ module TypeScript.Services.Formatting {
// Find the outer most parent that this closing brace terminates
var current: ISyntaxElement = closeBracePositionedToken;
while (current.parent !== null &&
- end(current.parent) === end(closeBracePositionedToken) &&
- current.parent.kind() !== SyntaxKind.List) {
+ end(current.parent) === end(closeBracePositionedToken) &&
+ current.parent.kind() !== SyntaxKind.List) {
current = current.parent;
}
@@ -86,7 +84,7 @@ module TypeScript.Services.Formatting {
return [];
}
- public formatOnEnter(caretPosition: number): ts.TextEdit[] {
+ public formatOnEnter(caretPosition: number): ts.TextChange[] {
var lineNumber = this.snapshot.getLineNumberFromPosition(caretPosition);
if (lineNumber > 0) {
@@ -103,23 +101,20 @@ module TypeScript.Services.Formatting {
return [];
}
- private formatSpan(span: TextSpan, formattingRequestKind: FormattingRequestKind): ts.TextEdit[] {
+ private formatSpan(span: TextSpan, formattingRequestKind: FormattingRequestKind): ts.TextChange[] {
// Always format from the beginning of the line
var startLine = this.snapshot.getLineFromPosition(span.start());
span = TextSpan.fromBounds(startLine.startPosition(), span.end());
- var result: ts.TextEdit[] = [];
+ var result: ts.TextChange[] = [];
var formattingEdits = Formatter.getEdits(span, this.syntaxTree.sourceUnit(), this.options, true, this.snapshot, this.rulesProvider, formattingRequestKind);
//
// TODO: Change the ILanguageService interface to return TextEditInfo (with start, and length) instead of TextEdit (with minChar and limChar)
formattingEdits.forEach((item) => {
- result.push({
- minChar: item.position,
- limChar: item.position + item.length,
- text: item.replaceWith
- });
+ var edit = new ts.TextChange(new TextSpan(item.position, item.length), item.replaceWith);
+ result.push(edit);
});
return result;
diff --git a/src/services/formatting/textSnapshot.ts b/src/services/formatting/textSnapshot.ts
index c91ea7ae492..4f2904dd76f 100644
--- a/src/services/formatting/textSnapshot.ts
+++ b/src/services/formatting/textSnapshot.ts
@@ -17,6 +17,7 @@
module TypeScript.Services.Formatting {
export interface ITextSnapshot {
+ getLength(): number;
getText(span: TextSpan): string;
getLineNumberFromPosition(position: number): number;
getLineFromPosition(position: number): ITextSnapshotLine;
@@ -30,6 +31,10 @@ module TypeScript.Services.Formatting {
this.lines = [];
}
+ public getLength(): number {
+ return this.snapshot.length();
+ }
+
public getText(span: TextSpan): string {
return this.snapshot.substr(span.start(), span.length());
}
diff --git a/src/services/getScriptLexicalStructureWalker.ts b/src/services/getScriptLexicalStructureWalker.ts
index b42f34fa927..bfce8e0067c 100644
--- a/src/services/getScriptLexicalStructureWalker.ts
+++ b/src/services/getScriptLexicalStructureWalker.ts
@@ -1,121 +1,22 @@
-
///
+
module TypeScript.Services {
- interface LexicalScope {
- items: ts.Map;
- itemNames: string[];
- childScopes: ts.Map;
- childScopeNames: string[];
- }
+ export class NavigationBarItemGetter {
+ private hasGlobalNode = false;
- export class GetScriptLexicalStructureWalker extends TypeScript.SyntaxWalker {
- private nameStack: string[] = [];
- private kindStack: string[] = [];
+ private getIndent(node: ISyntaxNode): number {
+ var indent = this.hasGlobalNode ? 1 : 0;
- private parentScopes: LexicalScope[] = [];
- private currentScope: LexicalScope;
+ var current = node.parent;
+ while (current != null) {
+ if (current.kind() == SyntaxKind.ModuleDeclaration || current.kind() === SyntaxKind.FunctionDeclaration) {
+ indent++;
+ }
- private createScope(): LexicalScope {
- return {
- items: TypeScript.createIntrinsicsObject(),
- childScopes: TypeScript.createIntrinsicsObject(),
- childScopeNames: [],
- itemNames: []
- };
- }
-
- private pushNewContainerScope(containerName: string, kind: string): LexicalScope {
- Debug.assert(containerName, "No scope name provided");
-
- var key = kind + "+" + containerName;
- this.nameStack.push(containerName);
- this.kindStack.push(kind);
-
- var parentScope = this.currentScope;
- this.parentScopes.push(parentScope);
-
- var scope = ts.lookUp(parentScope.childScopes, key);
- if (!scope) {
- scope = this.createScope()
- parentScope.childScopes[key] = scope;
- parentScope.childScopeNames.push(key);
+ current = current.parent;
}
- this.currentScope = scope;
- return parentScope;
- }
-
- private popScope() {
- Debug.assert(this.parentScopes.length > 0, "No parent scopes to return to")
- this.currentScope = this.parentScopes.pop();
- this.kindStack.pop();
- this.nameStack.pop();
- }
-
- constructor(private fileName: string) {
- super();
- this.currentScope = this.createScope();
- }
-
- private collectItems(items: ts.NavigateToItem[], scope = this.currentScope) {
- scope.itemNames.forEach(item => {
- items.push(scope.items[item]);
- });
-
- scope.childScopeNames.forEach(childScope => {
- this.collectItems(items, scope.childScopes[childScope]);
- });
- }
-
- static getListsOfAllScriptLexicalStructure(items: ts.NavigateToItem[], fileName: string, unit: TypeScript.SourceUnitSyntax) {
- var visitor = new GetScriptLexicalStructureWalker(fileName);
- visitNodeOrToken(visitor, unit);
- visitor.collectItems(items);
- }
-
- private createItem(node: TypeScript.ISyntaxNode, modifiers: ISyntaxToken[], kind: string, name: string): void {
- var key = kind + "+" + name;
-
- if (ts.lookUp(this.currentScope.items, key) !== undefined) {
- this.addAdditionalSpan(node, key);
- return;
- }
-
- var item: ts.NavigateToItem = {
- name: name,
- kind: kind,
- matchKind: ts.MatchKind.exact,
- fileName: this.fileName,
- kindModifiers: this.getKindModifiers(modifiers),
- minChar: start(node),
- limChar: end(node),
- containerName: this.nameStack.join("."),
- containerKind: this.kindStack.length === 0 ? "" : TypeScript.ArrayUtilities.last(this.kindStack),
- };
- this.currentScope.items[key] = item;
- this.currentScope.itemNames.push(key);
- }
-
- private addAdditionalSpan(
- node: TypeScript.ISyntaxNode,
- key: string) {
-
- var item = ts.lookUp(this.currentScope.items, key);
- Debug.assert(item !== undefined);
-
- var start = TypeScript.start(node);
- var span: ts.SpanInfo = {
- minChar: start,
- limChar: start + width(node)
- };
-
-
- if (item.additionalSpans) {
- item.additionalSpans.push(span);
- }
- else {
- item.additionalSpans = [span];
- }
+ return indent;
}
private getKindModifiers(modifiers: TypeScript.ISyntaxToken[]): string {
@@ -128,30 +29,221 @@ module TypeScript.Services {
return result.length > 0 ? result.join(',') : ts.ScriptElementKindModifier.none;
}
- public visitModuleDeclaration(node: TypeScript.ModuleDeclarationSyntax): void {
- var names = this.getModuleNames(node);
- this.visitModuleDeclarationWorker(node, names, 0);
+ public getItems(node: TypeScript.SourceUnitSyntax): ts.NavigationBarItem[] {
+ return this.getItemsWorker(() => this.getTopLevelNodes(node), n => this.createTopLevelItem(n));
}
- private visitModuleDeclarationWorker(node: TypeScript.ModuleDeclarationSyntax, names: string[], nameIndex: number): void {
- if (nameIndex === names.length) {
- // We're after all the module names, descend and process all children.
- super.visitModuleDeclaration(node);
+ private getChildNodes(nodes: IModuleElementSyntax[]): ISyntaxNode[] {
+ var childNodes: ISyntaxNode[] = [];
+
+ for (var i = 0, n = nodes.length; i < n; i++) {
+ var node = nodes[i];
+
+ if (node.kind() === SyntaxKind.FunctionDeclaration) {
+ childNodes.push(node);
+ }
+ else if (node.kind() === SyntaxKind.VariableStatement) {
+ var variableDeclaration = (node).variableDeclaration;
+ childNodes.push.apply(childNodes, variableDeclaration.variableDeclarators);
+ }
}
- else {
- var name = names[nameIndex];
- var kind = ts.ScriptElementKind.moduleElement;
- this.createItem(node, node.modifiers, kind, name);
+ return childNodes;
+ }
- this.pushNewContainerScope(name, kind);
+ private getTopLevelNodes(node: SourceUnitSyntax): ISyntaxNode[] {
+ var topLevelNodes: ISyntaxNode[] = [];
+ topLevelNodes.push(node);
- this.visitModuleDeclarationWorker(node, names, nameIndex + 1);
+ this.addTopLevelNodes(node.moduleElements, topLevelNodes);
- this.popScope();
+ return topLevelNodes;
+ }
+
+ private addTopLevelNodes(nodes: IModuleElementSyntax[], topLevelNodes: ISyntaxNode[]): void {
+ for (var i = 0, n = nodes.length; i < n; i++) {
+ var node = nodes[i];
+ switch (node.kind()) {
+ case SyntaxKind.ClassDeclaration:
+ case SyntaxKind.EnumDeclaration:
+ case SyntaxKind.InterfaceDeclaration:
+ topLevelNodes.push(node);
+ break;
+
+ case SyntaxKind.ModuleDeclaration:
+ var moduleDeclaration = node;
+ topLevelNodes.push(node);
+ this.addTopLevelNodes(moduleDeclaration.moduleElements, topLevelNodes);
+ break;
+
+ case SyntaxKind.FunctionDeclaration:
+ var functionDeclaration = node;
+ if (this.isTopLevelFunctionDeclaration(functionDeclaration)) {
+ topLevelNodes.push(node);
+ this.addTopLevelNodes(functionDeclaration.block.statements, topLevelNodes);
+ }
+ break;
+ }
}
}
+ public isTopLevelFunctionDeclaration(functionDeclaration: FunctionDeclarationSyntax) {
+ // A function declaration is 'top level' if it contains any function declarations
+ // within it.
+ return functionDeclaration.block && ArrayUtilities.any(functionDeclaration.block.statements, s => s.kind() === SyntaxKind.FunctionDeclaration);
+ }
+
+ private getItemsWorker(getNodes: () => ISyntaxNode[], createItem: (n: ISyntaxNode) => ts.NavigationBarItem): ts.NavigationBarItem[] {
+ var items: ts.NavigationBarItem[] = [];
+
+ var keyToItem = createIntrinsicsObject();
+
+ var nodes = getNodes();
+ for (var i = 0, n = nodes.length; i < n; i++) {
+ var child = nodes[i];
+ var item = createItem(child);
+ if (item != null) {
+ if (item.text.length > 0) {
+ var key = item.text + "-" + item.kind;
+
+ var itemWithSameName = keyToItem[key];
+ if (itemWithSameName) {
+ // We had an item with the same name. Merge these items together.
+ this.merge(itemWithSameName, item);
+ }
+ else {
+ keyToItem[key] = item;
+ items.push(item);
+ }
+ }
+ }
+ }
+
+ return items;
+ }
+
+ private merge(target: ts.NavigationBarItem, source: ts.NavigationBarItem) {
+ // First, add any spans in the source to the target.
+ target.spans.push.apply(target.spans, source.spans);
+
+ if (source.childItems) {
+ if (!target.childItems) {
+ target.childItems = [];
+ }
+
+ // Next, recursively merge or add any children in the source as appropriate.
+ outer:
+ for (var i = 0, n = source.childItems.length; i < n; i++) {
+ var sourceChild = source.childItems[i];
+
+ for (var j = 0, m = target.childItems.length; j < m; j++) {
+ var targetChild = target.childItems[j];
+
+ if (targetChild.text === sourceChild.text && targetChild.kind === sourceChild.kind) {
+ // Found a match. merge them.
+ this.merge(targetChild, sourceChild);
+ continue outer;
+ }
+ }
+
+ // Didn't find a match, just add this child to the list.
+ target.childItems.push(sourceChild);
+ }
+ }
+ }
+
+ private createChildItem(node: ISyntaxNode): ts.NavigationBarItem {
+ switch (node.kind()) {
+ case SyntaxKind.Parameter:
+ var parameter = node;
+ if (parameter.modifiers.length === 0) {
+ return null;
+ }
+ return new ts.NavigationBarItem(parameter.identifier.text(), ts.ScriptElementKind.memberVariableElement, this.getKindModifiers(parameter.modifiers), [TextSpan.fromBounds(start(node), end(node))]);
+
+ case SyntaxKind.MemberFunctionDeclaration:
+ var memberFunction = node;
+ return new ts.NavigationBarItem(memberFunction.propertyName.text(), ts.ScriptElementKind.memberFunctionElement, this.getKindModifiers(memberFunction.modifiers), [TextSpan.fromBounds(start(node), end(node))]);
+
+ case SyntaxKind.GetAccessor:
+ var getAccessor = node;
+ return new ts.NavigationBarItem(getAccessor.propertyName.text(), ts.ScriptElementKind.memberGetAccessorElement, this.getKindModifiers(getAccessor.modifiers), [TextSpan.fromBounds(start(node), end(node))]);
+
+ case SyntaxKind.SetAccessor:
+ var setAccessor = node;
+ return new ts.NavigationBarItem(setAccessor.propertyName.text(), ts.ScriptElementKind.memberSetAccessorElement, this.getKindModifiers(setAccessor.modifiers), [TextSpan.fromBounds(start(node), end(node))]);
+
+ case SyntaxKind.IndexSignature:
+ var indexSignature = node;
+ return new ts.NavigationBarItem("[]", ts.ScriptElementKind.indexSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
+
+ case SyntaxKind.EnumElement:
+ var enumElement = node;
+ return new ts.NavigationBarItem(enumElement.propertyName.text(), ts.ScriptElementKind.memberVariableElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
+
+ case SyntaxKind.CallSignature:
+ var callSignature = node;
+ return new ts.NavigationBarItem("()", ts.ScriptElementKind.callSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
+
+ case SyntaxKind.ConstructSignature:
+ var constructSignature = node;
+ return new ts.NavigationBarItem("new()", ts.ScriptElementKind.constructSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
+
+ case SyntaxKind.MethodSignature:
+ var methodSignature = node;
+ return new ts.NavigationBarItem(methodSignature.propertyName.text(), ts.ScriptElementKind.memberFunctionElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
+
+ case SyntaxKind.PropertySignature:
+ var propertySignature = node;
+ return new ts.NavigationBarItem(propertySignature.propertyName.text(), ts.ScriptElementKind.memberVariableElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
+
+ case SyntaxKind.FunctionDeclaration:
+ var functionDeclaration = node;
+ if (!this.isTopLevelFunctionDeclaration(functionDeclaration)) {
+ return new ts.NavigationBarItem(functionDeclaration.identifier.text(), ts.ScriptElementKind.functionElement, this.getKindModifiers(functionDeclaration.modifiers), [TextSpan.fromBounds(start(node), end(node))]);
+ }
+ break;
+
+ case SyntaxKind.MemberVariableDeclaration:
+ var memberVariableDeclaration = node;
+ return new ts.NavigationBarItem(memberVariableDeclaration.variableDeclarator.propertyName.text(), ts.ScriptElementKind.memberVariableElement, this.getKindModifiers(memberVariableDeclaration.modifiers), [TextSpan.fromBounds(start(memberVariableDeclaration.variableDeclarator), end(memberVariableDeclaration.variableDeclarator))]);
+
+ case SyntaxKind.VariableDeclarator:
+ var variableDeclarator = node;
+ return new ts.NavigationBarItem(variableDeclarator.propertyName.text(), ts.ScriptElementKind.variableElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(variableDeclarator), end(variableDeclarator))]);
+
+ case SyntaxKind.ConstructorDeclaration:
+ var constructorDeclaration = node;
+ return new ts.NavigationBarItem("constructor", ts.ScriptElementKind.constructorImplementationElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
+ }
+
+ return null;
+ }
+
+ private createTopLevelItem(node: ISyntaxNode): ts.NavigationBarItem {
+ switch (node.kind()) {
+ case SyntaxKind.SourceUnit:
+ return this.createSourceUnitItem(node);
+
+ case SyntaxKind.ClassDeclaration:
+ return this.createClassItem(node);
+
+ case SyntaxKind.EnumDeclaration:
+ return this.createEnumItem(node);
+
+ case SyntaxKind.InterfaceDeclaration:
+ return this.createIterfaceItem(node);
+
+ case SyntaxKind.ModuleDeclaration:
+ return this.createModuleItem(node);
+
+ case SyntaxKind.FunctionDeclaration:
+ return this.createFunctionItem(node);
+ }
+
+ return null;
+ }
+
private getModuleNames(node: TypeScript.ModuleDeclarationSyntax): string[] {
var result: string[] = [];
@@ -176,180 +268,84 @@ module TypeScript.Services {
}
}
- public visitClassDeclaration(node: TypeScript.ClassDeclarationSyntax): void {
- var name = node.identifier.text();
- var kind = ts.ScriptElementKind.classElement;
+ private createModuleItem(node: ModuleDeclarationSyntax): ts.NavigationBarItem {
+ var moduleNames = this.getModuleNames(node);
- this.createItem(node, node.modifiers, kind, name);
+ var childItems = this.getItemsWorker(() => this.getChildNodes(node.moduleElements), n => this.createChildItem(n));
- this.pushNewContainerScope(name, kind);
-
- super.visitClassDeclaration(node);
-
- this.popScope();
+ return new ts.NavigationBarItem(moduleNames.join("."),
+ ts.ScriptElementKind.moduleElement,
+ this.getKindModifiers(node.modifiers),
+ [TextSpan.fromBounds(start(node), end(node))],
+ childItems,
+ this.getIndent(node));
}
- public visitInterfaceDeclaration(node: TypeScript.InterfaceDeclarationSyntax): void {
- var name = node.identifier.text();
- var kind = ts.ScriptElementKind.interfaceElement;
+ private createFunctionItem(node: FunctionDeclarationSyntax) {
+ var childItems = this.getItemsWorker(() => node.block.statements, n => this.createChildItem(n));
- this.createItem(node, node.modifiers, kind, name);
-
- this.pushNewContainerScope(name, kind);
-
- super.visitInterfaceDeclaration(node);
-
- this.popScope();
+ return new ts.NavigationBarItem(node.identifier.text(),
+ ts.ScriptElementKind.functionElement,
+ this.getKindModifiers(node.modifiers),
+ [TextSpan.fromBounds(start(node), end(node))],
+ childItems,
+ this.getIndent(node));
}
- public visitObjectType(node: TypeScript.ObjectTypeSyntax): void {
- // Ignore an object type if we aren't inside an interface declaration. We don't want
- // to add some random object type's members to the nav bar.
- if (node.parent.kind() === SyntaxKind.InterfaceDeclaration) {
- super.visitObjectType(node);
- }
- }
+ private createSourceUnitItem(node: SourceUnitSyntax): ts.NavigationBarItem {
+ var childItems = this.getItemsWorker(() => this.getChildNodes(node.moduleElements), n => this.createChildItem(n));
- public visitEnumDeclaration(node: TypeScript.EnumDeclarationSyntax): void {
- var name = node.identifier.text();
- var kind = ts.ScriptElementKind.enumElement;
-
- this.createItem(node, node.modifiers, kind, name);
-
- this.pushNewContainerScope(name, kind);
-
- super.visitEnumDeclaration(node);
-
- this.popScope();
- }
-
- public visitConstructorDeclaration(node: TypeScript.ConstructorDeclarationSyntax): void {
- this.createItem(node, TypeScript.Syntax.emptyList(), ts.ScriptElementKind.constructorImplementationElement, "constructor");
-
- // Search the parameter list of class properties
- var parameters = node.callSignature.parameterList.parameters;
- if (parameters) {
- for (var i = 0, n = parameters.length; i < n; i++) {
- var parameter = parameters[i];
-
- Debug.assert(parameter.kind() === SyntaxKind.Parameter);
-
- if (SyntaxUtilities.containsToken(parameter.modifiers, SyntaxKind.PublicKeyword) ||
- SyntaxUtilities.containsToken(parameter.modifiers, SyntaxKind.PrivateKeyword)) {
- this.createItem(node, parameter.modifiers, ts.ScriptElementKind.memberVariableElement, parameter.identifier.text());
- }
- }
+ if (childItems === null || childItems.length === 0) {
+ return null;
}
- // No need to descend into a constructor;
+ this.hasGlobalNode = true;
+ return new ts.NavigationBarItem("",
+ ts.ScriptElementKind.moduleElement,
+ ts.ScriptElementKindModifier.none,
+ [TextSpan.fromBounds(start(node), end(node))],
+ childItems);
}
- public visitMemberFunctionDeclaration(node: TypeScript.MemberFunctionDeclarationSyntax): void {
- this.createItem(node, node.modifiers, ts.ScriptElementKind.memberFunctionElement, node.propertyName.text());
+ private createClassItem(node: ClassDeclarationSyntax): ts.NavigationBarItem {
+ var constructor = ArrayUtilities.firstOrDefault(
+ node.classElements, n => n.kind() === SyntaxKind.ConstructorDeclaration);
- // No need to descend into a member function;
+ // Add the constructor parameters in as children of hte class (for property parameters).
+ var nodes: ISyntaxNode[] = constructor
+ ? (constructor.callSignature.parameterList.parameters).concat(node.classElements)
+ : node.classElements;
+
+ var childItems = this.getItemsWorker(() => nodes, n => this.createChildItem(n));
+ return new ts.NavigationBarItem(
+ node.identifier.text(),
+ ts.ScriptElementKind.classElement,
+ this.getKindModifiers(node.modifiers),
+ [TextSpan.fromBounds(start(node), end(node))],
+ childItems,
+ this.getIndent(node));
}
- public visitGetAccessor(node: TypeScript.GetAccessorSyntax): void {
- this.createItem(node, node.modifiers, ts.ScriptElementKind.memberGetAccessorElement, node.propertyName.text());
-
- // No need to descend into a member accessor;
+ private createEnumItem(node: TypeScript.EnumDeclarationSyntax): ts.NavigationBarItem {
+ var childItems = this.getItemsWorker(() => node.enumElements, n => this.createChildItem(n));
+ return new ts.NavigationBarItem(
+ node.identifier.text(),
+ ts.ScriptElementKind.enumElement,
+ this.getKindModifiers(node.modifiers),
+ [TextSpan.fromBounds(start(node), end(node))],
+ childItems,
+ this.getIndent(node));
}
- public visitSetAccessor(node: TypeScript.SetAccessorSyntax): void {
- this.createItem(node, node.modifiers, ts.ScriptElementKind.memberSetAccessorElement, node.propertyName.text());
-
- // No need to descend into a member accessor;
- }
-
- public visitVariableDeclarator(node: TypeScript.VariableDeclaratorSyntax): void {
- var modifiers = node.parent.kind() === SyntaxKind.MemberVariableDeclaration
- ? (node.parent).modifiers
- : TypeScript.Syntax.emptyList();
- var kind = node.parent.kind() === SyntaxKind.MemberVariableDeclaration
- ? ts.ScriptElementKind.memberVariableElement
- : ts.ScriptElementKind.variableElement;
- this.createItem(node, modifiers, kind, node.propertyName.text());
-
- // No need to descend into a variable declarator;
- }
-
- public visitIndexSignature(node: TypeScript.IndexSignatureSyntax): void {
- this.createItem(node, TypeScript.Syntax.emptyList(), ts.ScriptElementKind.indexSignatureElement, "[]");
-
- // No need to descend into an index signature;
- }
-
- public visitEnumElement(node: TypeScript.EnumElementSyntax): void {
- this.createItem(node, TypeScript.Syntax.emptyList(), ts.ScriptElementKind.memberVariableElement, node.propertyName.text());
-
- // No need to descend into an enum element;
- }
-
- public visitCallSignature(node: TypeScript.CallSignatureSyntax): void {
- this.createItem(node, TypeScript.Syntax.emptyList(), ts.ScriptElementKind.callSignatureElement, "()");
-
- // No need to descend into a call signature;
- }
-
- public visitConstructSignature(node: TypeScript.ConstructSignatureSyntax): void {
- this.createItem(node, TypeScript.Syntax.emptyList(), ts.ScriptElementKind.constructSignatureElement, "new()");
-
- // No need to descend into a construct signature;
- }
-
- public visitMethodSignature(node: TypeScript.MethodSignatureSyntax): void {
- this.createItem(node, TypeScript.Syntax.emptyList(), ts.ScriptElementKind.memberFunctionElement, node.propertyName.text());
-
- // No need to descend into a method signature;
- }
-
- public visitPropertySignature(node: TypeScript.PropertySignatureSyntax): void {
- this.createItem(node, TypeScript.Syntax.emptyList(), ts.ScriptElementKind.memberVariableElement, node.propertyName.text());
-
- // No need to descend into a property signature;
- }
-
- public visitFunctionDeclaration(node: TypeScript.FunctionDeclarationSyntax): void {
- // in the case of:
- // declare function
- // the parser will synthesize an identifier.
- // we shouldn't add an unnamed function declaration
- if (width(node.identifier) > 0) {
- this.createItem(node, node.modifiers, ts.ScriptElementKind.functionElement, node.identifier.text());
- }
-
- // No need to descend into a function declaration;
- }
-
- // Common statement types. Don't even bother walking into them as we'll never find anything
- // inside that we'd put in the navbar.
-
- public visitBlock(node: TypeScript.BlockSyntax): void {
- }
-
- public visitIfStatement(node: TypeScript.IfStatementSyntax): void {
- }
-
- public visitExpressionStatement(node: TypeScript.ExpressionStatementSyntax): void {
- }
-
- public visitThrowStatement(node: TypeScript.ThrowStatementSyntax): void {
- }
-
- public visitReturnStatement(node: TypeScript.ReturnStatementSyntax): void {
- }
-
- public visitSwitchStatement(node: TypeScript.SwitchStatementSyntax): void {
- }
-
- public visitWithStatement(node: TypeScript.WithStatementSyntax): void {
- }
-
- public visitTryStatement(node: TypeScript.TryStatementSyntax): void {
- }
-
- public visitLabeledStatement(node: TypeScript.LabeledStatementSyntax): void {
+ private createIterfaceItem(node: TypeScript.InterfaceDeclarationSyntax): ts.NavigationBarItem {
+ var childItems = this.getItemsWorker(() => node.body.typeMembers, n => this.createChildItem(n));
+ return new ts.NavigationBarItem(
+ node.identifier.text(),
+ ts.ScriptElementKind.interfaceElement,
+ this.getKindModifiers(node.modifiers),
+ [TextSpan.fromBounds(start(node), end(node))],
+ childItems,
+ this.getIndent(node));
}
}
}
\ No newline at end of file
diff --git a/src/services/services.ts b/src/services/services.ts
index 9ff6266d54e..201b43432d3 100644
--- a/src/services/services.ts
+++ b/src/services/services.ts
@@ -458,9 +458,6 @@ module ts {
// with a language service host instance
//
export interface LanguageService {
- // Note: refresh is a no-op now. It is only around for back compat purposes.
- refresh(): void;
-
cleanupSemanticCache(): void;
getSyntacticDiagnostics(fileName: string): Diagnostic[];
@@ -472,28 +469,30 @@ module ts {
getTypeAtPosition(fileName: string, position: number): TypeInfo;
- getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): SpanInfo;
+ getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TypeScript.TextSpan;
- getBreakpointStatementAtPosition(fileName: string, position: number): SpanInfo;
+ getBreakpointStatementAtPosition(fileName: string, position: number): TypeScript.TextSpan;
- getSignatureAtPosition(fileName: string, position: number): SignatureInfo;
+ getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems;
+ getSignatureHelpCurrentArgumentState(fileName: string, position: number, applicableSpanStart: number): SignatureHelpState;
+ getRenameInfo(fileName: string, position: number): RenameInfo;
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[];
getImplementorsAtPosition(fileName: string, position: number): ReferenceEntry[];
getNavigateToItems(searchValue: string): NavigateToItem[];
- getScriptLexicalStructure(fileName: string): NavigateToItem[];
+ getNavigationBarItems(fileName: string): NavigationBarItem[];
- getOutliningRegions(fileName: string): OutliningSpan[];
+ getOutliningSpans(fileName: string): OutliningSpan[];
+ getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[];
getBraceMatchingAtPosition(fileName: string, position: number): TypeScript.TextSpan[];
getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number;
- getFormattingEditsForRange(fileName: string, minChar: number, limChar: number, options: FormatCodeOptions): TextEdit[];
- getFormattingEditsForDocument(fileName: string, minChar: number, limChar: number, options: FormatCodeOptions): TextEdit[];
- getFormattingEditsOnPaste(fileName: string, minChar: number, limChar: number, options: FormatCodeOptions): TextEdit[];
- getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextEdit[];
+ getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[];
+ getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[];
+ getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[];
getEmitOutput(fileName: string): EmitOutput;
@@ -502,30 +501,68 @@ module ts {
dispose(): void;
}
- export interface ReferenceEntry {
- fileName: string;
- minChar: number;
- limChar: number;
- isWriteAccess: boolean;
+ export class NavigationBarItem {
+ constructor(public text: string,
+ public kind: string,
+ public kindModifiers: string,
+ public spans: TypeScript.TextSpan[],
+ public childItems: NavigationBarItem[] = null,
+ public indent = 0,
+ public bolded = false,
+ public grayed = false) {
+ }
}
- export interface NavigateToItem {
- name: string;
- kind: string; // see ScriptElementKind
- kindModifiers: string; // see ScriptElementKindModifier, comma separated
- matchKind: string;
- fileName: string;
- minChar: number;
- limChar: number;
- additionalSpans?: SpanInfo[];
- containerName: string;
- containerKind: string; // see ScriptElementKind
+ export class TodoCommentDescriptor {
+ constructor(public text: string,
+ public priority: number) {
+ }
}
- export interface TextEdit {
- minChar: number;
- limChar: number;
- text: string;
+ export class TodoComment {
+ constructor(public descriptor: TodoCommentDescriptor,
+ public message: string,
+ public position: number) {
+ }
+ }
+
+ export class TextChange {
+ constructor(public span: TypeScript.TextSpan, public newText: string) {
+ }
+
+ static createInsert(pos: number, newText: string): TextChange {
+ return new TextChange(new TypeScript.TextSpan(pos, 0), newText);
+ }
+ static createDelete(start: number, end: number): TextChange {
+ return new TextChange(TypeScript.TextSpan.fromBounds(start, end), "");
+ }
+ static createReplace(start: number, end: number, newText: string): TextChange {
+ return new TextChange(TypeScript.TextSpan.fromBounds(start, end), newText);
+ }
+ }
+
+ export class ReferenceEntry {
+ public fileName: string = "";
+ public textSpan: TypeScript.TextSpan;
+ public isWriteAccess: boolean = false;
+
+ constructor(fileName: string, textSpan: TypeScript.TextSpan, isWriteAccess: boolean) {
+ this.fileName = fileName;
+ this.textSpan = textSpan;
+ this.isWriteAccess = isWriteAccess;
+ }
+ }
+
+ export class NavigateToItem {
+ constructor(public name: string,
+ public kind: string,
+ public kindModifiers: string,
+ public matchKind: string,
+ public fileName: string,
+ public textSpan: TypeScript.TextSpan,
+ public containerName: string,
+ public containerKind: string) {
+ }
}
export interface EditorOptions {
@@ -546,14 +583,14 @@ module ts {
PlaceOpenBraceOnNewLineForControlBlocks: boolean;
}
- export interface DefinitionInfo {
- fileName: string;
- minChar: number;
- limChar: number;
- kind: string;
- name: string;
- containerKind: string;
- containerName: string;
+ export class DefinitionInfo {
+ constructor(public fileName: string,
+ public textSpan: TypeScript.TextSpan,
+ public kind: string,
+ public name: string,
+ public containerKind: string,
+ public containerName: string) {
+ }
}
export interface MemberName {
@@ -562,54 +599,80 @@ module ts {
text: string;
}
- export interface TypeInfo {
- memberName: MemberName;
- docComment: string;
- fullSymbolName: string;
- kind: string;
- minChar: number;
- limChar: number;
+ export class TypeInfo {
+ constructor(
+ public memberName: TypeScript.MemberName,
+ public docComment: string,
+ public fullSymbolName: string,
+ public kind: string,
+ public textSpan: TypeScript.TextSpan) {
+ }
}
- export interface SpanInfo {
- minChar: number;
- limChar: number;
- // text?: string;
+ export class RenameInfo {
+ constructor(public canRename: boolean,
+ public localizedErrorMessage: string,
+ public displayName: string,
+ public fullDisplayName: string,
+ public kind: string,
+ public kindModifiers: string,
+ public triggerSpan: TypeScript.TextSpan) {
+ }
+
+ public static CreateError(localizedErrorMessage: string) {
+ return new RenameInfo(/*canRename:*/ false, localizedErrorMessage,
+ /*displayName:*/ null, /*fullDisplayName:*/ null,
+ /*kind:*/ null, /*kindModifiers:*/ null, /*triggerSpan:*/ null);
+ }
+
+ public static Create(displayName: string,
+ fullDisplayName: string,
+ kind: string,
+ kindModifiers: string,
+ triggerSpan: TypeScript.TextSpan) {
+ return new RenameInfo(/*canRename:*/ true, /*localizedErrorMessage:*/ null, displayName, fullDisplayName, kind, kindModifiers, triggerSpan);
+ }
}
- export interface SignatureInfo {
- actual: ActualSignatureInfo;
- formal: FormalSignatureItemInfo[]; // Formal signatures
- activeFormal: number; // Index of the "best match" formal signature
+ export class SignatureHelpParameter {
+ constructor(public name: string,
+ public documentation: string,
+ public display: string,
+ public isOptional: boolean) {
+ }
}
- export interface FormalSignatureItemInfo {
- signatureInfo: string;
- typeParameters: FormalTypeParameterInfo[];
- parameters: FormalParameterInfo[]; // Array of parameters
- docComment: string; // Help for the signature
+ /**
+ * Represents a single signature to show in signature help.
+ * The id is used for subsequent calls into the language service to ask questions about the
+ * signature help item in the context of any documents that have been updated. i.e. after
+ * an edit has happened, while signature help is still active, the host can ask important
+ * questions like 'what parameter is the user currently contained within?'.
+ */
+ export class SignatureHelpItem {
+ constructor(public isVariadic: boolean,
+ public prefix: string,
+ public suffix: string,
+ public separator: string,
+ public parameters: SignatureHelpParameter[],
+ public documentation: string) {
+ }
}
- export interface FormalTypeParameterInfo {
- name: string; // Type parameter name
- docComment: string; // Comments that contain help for the parameter
- minChar: number; // minChar for parameter info in the formal signature info string
- limChar: number; // lim char for parameter info in the formal signature info string
+ /**
+ * Represents a set of signature help items, and the preferred item that should be selected.
+ */
+ export class SignatureHelpItems {
+ constructor(public items: SignatureHelpItem[],
+ public applicableSpan: TypeScript.TextSpan,
+ public selectedItemIndex: number) {
+ }
}
- export interface FormalParameterInfo {
- name: string; // Parameter name
- isVariable: boolean; // true if parameter is var args
- docComment: string; // Comments that contain help for the parameter
- minChar: number; // minChar for parameter info in the formal signature info string
- limChar: number; // lim char for parameter info in the formal signature info string
- }
-
- export interface ActualSignatureInfo {
- parameterMinChar: number;
- parameterLimChar: number;
- currentParameterIsTypeParameter: boolean; // current parameter is a type argument or a normal argument
- currentParameter: number; // Index of active parameter in "parameters" or "typeParamters" array
+ export class SignatureHelpState {
+ constructor(public argumentIndex: number,
+ public argumentCount: number) {
+ }
}
export interface CompletionInfo {
@@ -1877,25 +1940,21 @@ module ts {
}
/// QuickInfo
- function getTypeAtPosition(filename: string, position: number): TypeInfo {
+ function getTypeAtPosition(fileName: string, position: number): TypeInfo {
synchronizeHostData();
- filename = TypeScript.switchToForwardSlashes(filename);
- var sourceFile = getSourceFile(filename);
+ fileName = TypeScript.switchToForwardSlashes(fileName);
+ var sourceFile = getSourceFile(fileName);
var node = getNodeAtPosition(sourceFile.getSourceFile(), position);
if (!node) return undefined;
var symbol = typeChecker.getSymbolInfo(node);
var type = symbol && typeChecker.getTypeOfSymbol(symbol);
if (type) {
- return {
- memberName: new TypeScript.MemberNameString(typeChecker.typeToString(type)),
- docComment: "",
- fullSymbolName: typeChecker.symbolToString(symbol, getContainerNode(node)),
- kind: getSymbolKind(symbol),
- minChar: node.pos,
- limChar: node.end
- };
+ return new TypeInfo(
+ new TypeScript.MemberNameString(typeChecker.typeToString(type)),
+ "", typeChecker.symbolToString(symbol, getContainerNode(node)),
+ getSymbolKind(symbol), TypeScript.TextSpan.fromBounds(node.pos, node.end));
}
return undefined;
@@ -1950,15 +2009,13 @@ module ts {
}
function getDefinitionInfo(node: Node, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo {
- return {
- fileName: node.getSourceFile().filename,
- minChar: node.getStart(),
- limChar: node.getEnd(),
- kind: symbolKind,
- name: symbolName,
- containerName: containerName,
- containerKind: undefined
- };
+ return new DefinitionInfo(
+ node.getSourceFile().filename,
+ TypeScript.TextSpan.fromBounds(node.getStart(), node.getEnd()),
+ symbolKind,
+ symbolName,
+ undefined,
+ containerName);
}
function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) {
@@ -2028,11 +2085,10 @@ module ts {
if (comment) {
var targetFilename = normalizePath(combinePaths(getDirectoryPath(filename), comment.filename));
if (program.getSourceFile(targetFilename)) {
- return [{
- fileName: targetFilename, minChar: 0, limChar: 0,
- kind: ScriptElementKind.scriptElement,
- name: comment.filename, containerName: undefined, containerKind: undefined
- }];
+ return [new DefinitionInfo(
+ targetFilename, TypeScript.TextSpan.fromBounds(0, 0),
+ ScriptElementKind.scriptElement,
+ comment.filename, undefined, undefined)];
}
return undefined;
}
@@ -2077,7 +2133,7 @@ module ts {
return currentSourceFile;
}
- function getNameOrDottedNameSpan(filename: string, startPos: number, endPos: number): SpanInfo {
+ function getNameOrDottedNameSpan(filename: string, startPos: number, endPos: number): TypeScript.TextSpan {
function getTypeInfoEligiblePath(filename: string, position: number, isConstructorValidPosition: boolean) {
var sourceUnit = syntaxTreeCache.getCurrentFileSyntaxTree(filename).sourceUnit();
@@ -2128,10 +2184,9 @@ module ts {
}
}
- return {
- minChar: TypeScript.start(node),
- limChar: TypeScript.end(node)
- };
+ return TypeScript.TextSpan.fromBounds(
+ TypeScript.start(node),
+ TypeScript.end(node));
}
function getBreakpointStatementAtPosition(filename: string, position: number) {
@@ -2142,15 +2197,13 @@ module ts {
return TypeScript.Services.Breakpoints.getBreakpointLocation(syntaxtree, position);
}
- function getScriptLexicalStructure(filename: string) {
+ function getNavigationBarItems(filename: string) {
filename = TypeScript.switchToForwardSlashes(filename);
var syntaxTree = getSyntaxTree(filename);
- var items: NavigateToItem[] = [];
- TypeScript.Services.GetScriptLexicalStructureWalker.getListsOfAllScriptLexicalStructure(items, filename, syntaxTree.sourceUnit());
- return items;
+ return new TypeScript.Services.NavigationBarItemGetter().getItems(syntaxTree.sourceUnit());
}
- function getOutliningRegions(filename: string): OutliningSpan[] {
+ function getOutliningSpans(filename: string): OutliningSpan[] {
// doesn't use compiler - no need to synchronize with host
filename = TypeScript.switchToForwardSlashes(filename);
var sourceFile = getCurrentSourceFile(filename);
@@ -2197,41 +2250,191 @@ module ts {
return manager;
}
- function getFormattingEditsForRange(filename: string, minChar: number, limChar: number, options: FormatCodeOptions): TextEdit[] {
- filename = TypeScript.switchToForwardSlashes(filename);
+ function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] {
+ fileName = TypeScript.switchToForwardSlashes(fileName);
- var manager = getFormattingManager(filename, options);
- return manager.formatSelection(minChar, limChar);
+ var manager = getFormattingManager(fileName, options);
+ return manager.formatSelection(start, end);
}
- function getFormattingEditsForDocument(filename: string, minChar: number, limChar: number, options: FormatCodeOptions): TextEdit[] {
- filename = TypeScript.switchToForwardSlashes(filename);
+ function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] {
+ fileName = TypeScript.switchToForwardSlashes(fileName);
- var manager = getFormattingManager(filename, options);
- return manager.formatDocument(minChar, limChar);
+ var manager = getFormattingManager(fileName, options);
+ return manager.formatDocument();
}
- function getFormattingEditsOnPaste(filename: string, minChar: number, limChar: number, options: FormatCodeOptions): TextEdit[] {
- filename = TypeScript.switchToForwardSlashes(filename);
+ function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] {
+ fileName = TypeScript.switchToForwardSlashes(fileName);
- var manager = getFormattingManager(filename, options);
- return manager.formatOnPaste(minChar, limChar);
+ var manager = getFormattingManager(fileName, options);
+
+ if (key === "}") {
+ return manager.formatOnClosingCurlyBrace(position);
+ }
+ else if (key === ";") {
+ return manager.formatOnSemicolon(position);
+ }
+ else if (key === "\n") {
+ return manager.formatOnEnter(position);
+ }
+
+ return [];
}
- function getFormattingEditsAfterKeystroke(filename: string, position: number, key: string, options: FormatCodeOptions): TextEdit[] {
- filename = TypeScript.switchToForwardSlashes(filename);
+ function getTodoCommentsRegExp(descriptors: TodoCommentDescriptor[]): RegExp {
+ // NOTE: ?: means 'non-capture group'. It allows us to have groups without having to
+ // filter them out later in the final result array.
- var manager = getFormattingManager(filename, options);
- if (key === "}") return manager.formatOnClosingCurlyBrace(position);
- else if (key === ";") return manager.formatOnSemicolon(position);
- else if (key === "\n") return manager.formatOnEnter(position);
- else return [];
+ // TODO comments can appear in one of the following forms:
+ //
+ // 1) // TODO or /////////// TODO
+ //
+ // 2) /* TODO or /********** TODO
+ //
+ // 3) /*
+ // * TODO
+ // */
+ //
+ // The following three regexps are used to match the start of the text up to the TODO
+ // comment portion.
+ var singleLineCommentStart = /(?:\/\/+\s*)/.source;
+ var multiLineCommentStart = /(?:\/\*+\s*)/.source;
+ var anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source;
+
+ // Match any of the above three TODO comment start regexps.
+ // Note that the outermost group *is* a capture group. We want to capture the preamble
+ // so that we can determine the starting position of the TODO comment match.
+ var preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")";
+
+ // Takes the descriptors and forms a regexp that matches them as if they were literals.
+ // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be:
+ //
+ // (?:(TODO\(jason\))|(HACK))
+ //
+ // Note that the outermost group is *not* a capture group, but the innermost groups
+ // *are* capture groups. By capturing the inner literals we can determine after
+ // matching which descriptor we are dealing with.
+ var literals = "(?:" + descriptors.map(d => "(" + this.escapeRegExp(d.text) + ")").join("|") + ")";
+
+ // After matching a descriptor literal, the following regexp matches the rest of the
+ // text up to the end of the line (or */).
+ var endOfLineOrEndOfComment = /(?:$|\*\/)/.source
+ var messageRemainder = /(?:.*?)/.source
+
+ // This is the portion of the match we'll return as part of the TODO comment result. We
+ // match the literal portion up to the end of the line or end of comment.
+ var messagePortion = "(" + literals + messageRemainder + ")";
+ var regExpString = preamble + messagePortion + endOfLineOrEndOfComment;
+
+ // The final regexp will look like this:
+ // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim
+
+ // The flags of the regexp are important here.
+ // 'g' is so that we are doing a global search and can find matches several times
+ // in the input.
+ //
+ // 'i' is for case insensitivity (We do this to match C# TODO comment code).
+ //
+ // 'm' is so we can find matches in a multiline input.
+ return new RegExp(regExpString, "gim");
}
+ function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] {
+ fileName = TypeScript.switchToForwardSlashes(fileName);
+
+ var syntaxTree = this.compiler.getDocument(fileName).syntaxTree();
+ this.cancellationToken.throwIfCancellationRequested();
+
+ var text = syntaxTree.text;
+ var fileContents = text.substr(0, text.length());
+ this.cancellationToken.throwIfCancellationRequested();
+
+ var result: TodoComment[] = [];
+
+ if (descriptors.length > 0) {
+ var regExp = this.getTodoCommentsRegExp(descriptors);
+
+ var matchArray: RegExpExecArray;
+ while (matchArray = regExp.exec(fileContents)) {
+ this.cancellationToken.throwIfCancellationRequested();
+
+ // If we got a match, here is what the match array will look like. Say the source text is:
+ //
+ // " // hack 1"
+ //
+ // The result array with the regexp: will be:
+ //
+ // ["// hack 1", "// ", "hack 1", undefined, "hack"]
+ //
+ // Here are the relevant capture groups:
+ // 0) The full match for hte entire regex.
+ // 1) The preamble to the message portion.
+ // 2) The message portion.
+ // 3...N) The descriptor that was matched - by index. 'undefined' for each
+ // descriptor that didn't match. an actual value if it did match.
+ //
+ // i.e. 'undefined' in position 3 above means TODO(jason) didn't match.
+ // "hack" in position 4 means HACK did match.
+ var firstDescriptorCaptureIndex = 3;
+ Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex);
+
+ var preamble = matchArray[1];
+ var matchPosition = matchArray.index + preamble.length;
+
+ // Ok, we have found a match in the file. This is ony an acceptable match if
+ // it is contained within a comment.
+ var token = TypeScript.findToken(syntaxTree.sourceUnit(), matchPosition);
+
+ if (matchPosition >= TypeScript.start(token) && matchPosition < TypeScript.end(token)) {
+ // match was within the token itself. Not in the comment. Keep searching
+ // descriptor.
+ continue;
+ }
+
+ // Looks to be within the trivia. See if we can find hte comment containing it.
+ var triviaList = matchPosition < TypeScript.start(token) ? token.leadingTrivia(syntaxTree.text) : token.trailingTrivia(syntaxTree.text);
+ var trivia = this.findContainingComment(triviaList, matchPosition);
+ if (trivia === null) {
+ continue;
+ }
+
+ var descriptor: TodoCommentDescriptor = undefined;
+ for (var i = 0, n = descriptors.length; i < n; i++) {
+ if (matchArray[i + firstDescriptorCaptureIndex]) {
+ descriptor = descriptors[i];
+ }
+ }
+ Debug.assert(descriptor);
+
+ // We don't want to match something like 'TODOBY', so we make sure a non
+ // letter/digit follows the match.
+ if (this.isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) {
+ continue;
+ }
+
+ var message = matchArray[2];
+ result.push(new TodoComment(descriptor, message, matchPosition));
+ }
+ }
+
+ return result;
+ }
+
+ function findContainingComment(triviaList: TypeScript.ISyntaxTriviaList, position: number): TypeScript.ISyntaxTrivia {
+ for (var i = 0, n = triviaList.count(); i < n; i++) {
+ var trivia = triviaList.syntaxTriviaAt(i);
+ var fullEnd = trivia.fullStart() + trivia.fullWidth();
+ if (trivia.isComment() && trivia.fullStart() <= position && position < fullEnd) {
+ return trivia;
+ }
+ }
+
+ return null;
+ }
return {
dispose: dispose,
- refresh: () => { },
cleanupSemanticCache: cleanupSemanticCache,
getSyntacticDiagnostics: getSyntacticDiagnostics,
getSemanticDiagnostics: getSemanticDiagnostics,
@@ -2239,7 +2442,8 @@ module ts {
getCompletionsAtPosition: getCompletionsAtPosition,
getCompletionEntryDetails: getCompletionEntryDetails,
getTypeAtPosition: getTypeAtPosition,
- getSignatureAtPosition: (filename, position): SignatureInfo => undefined,
+ getSignatureHelpItems: (filename, position): SignatureHelpItems => null,
+ getSignatureHelpCurrentArgumentState: (fileName, position, applicableSpanStart): SignatureHelpState => null,
getDefinitionAtPosition: getDefinitionAtPosition,
getReferencesAtPosition: (filename, position) => [],
getOccurrencesAtPosition: (filename, position) => [],
@@ -2247,15 +2451,16 @@ module ts {
getNameOrDottedNameSpan: getNameOrDottedNameSpan,
getBreakpointStatementAtPosition: getBreakpointStatementAtPosition,
getNavigateToItems: (searchValue) => [],
- getScriptLexicalStructure: getScriptLexicalStructure,
- getOutliningRegions: getOutliningRegions,
+ getRenameInfo: (fileName, position): RenameInfo => null,
+ getNavigationBarItems: getNavigationBarItems,
+ getOutliningSpans: getOutliningSpans,
+ getTodoComments: getTodoComments,
getBraceMatchingAtPosition: getBraceMatchingAtPosition,
getIndentationAtPosition: getIndentationAtPosition,
getFormattingEditsForRange: getFormattingEditsForRange,
getFormattingEditsForDocument: getFormattingEditsForDocument,
- getFormattingEditsOnPaste: getFormattingEditsOnPaste,
getFormattingEditsAfterKeystroke: getFormattingEditsAfterKeystroke,
- getEmitOutput: (filename): EmitOutput => undefined,
+ getEmitOutput: (filename): EmitOutput => null,
};
}
diff --git a/src/services/shims.ts b/src/services/shims.ts
index d473a6979ee..d62b894f5a5 100644
--- a/src/services/shims.ts
+++ b/src/services/shims.ts
@@ -86,44 +86,51 @@ module ts {
getTypeAtPosition(fileName: string, position: number): string;
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): string;
getBreakpointStatementAtPosition(fileName: string, position: number): string;
- getSignatureAtPosition(fileName: string, position: number): string;
+
+ getSignatureHelpItems(fileName: string, position: number): string;
+ getSignatureHelpCurrentArgumentState(fileName: string, position: number, applicableSpanStart: number): string;
// Returns a JSON encoded value of the type:
- // { fileName: string; minChar: number; limChar: number; kind: string; name: string; containerKind: string; containerName: string }
+ // { canRename: boolean, localizedErrorMessage: string, displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, triggerSpan: { start; length } }
+ getRenameInfo(fileName: string, position: number): string;
+
+ // Returns a JSON encoded value of the type:
+ // { fileName: string; textSpan: { start: number; length: number}; kind: string; name: string; containerKind: string; containerName: string }
//
// Or null value if no definition can be found.
getDefinitionAtPosition(fileName: string, position: number): string;
// Returns a JSON encoded value of the type:
- // { fileName: string; minChar: number; limChar: number; isWriteAccess: boolean }[]
+ // { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
getReferencesAtPosition(fileName: string, position: number): string;
// Returns a JSON encoded value of the type:
- // { fileName: string; minChar: number; limChar: number; isWriteAccess: boolean }[]
+ // { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
getOccurrencesAtPosition(fileName: string, position: number): string;
// Returns a JSON encoded value of the type:
- // { fileName: string; minChar: number; limChar: number; isWriteAccess: boolean }[]
+ // { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
getImplementorsAtPosition(fileName: string, position: number): string;
// Returns a JSON encoded value of the type:
- // { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; minChar: number; limChar: number; } [] = [];
+ // { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; textSpan: { start: number; length: number}; } [] = [];
getNavigateToItems(searchValue: string): string;
// Returns a JSON encoded value of the type:
- // { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; minChar: number; limChar: number; } [] = [];
- getScriptLexicalStructure(fileName: string): string;
+ // { text: string; kind: string; kindModifiers: string; bolded: boolean; grayed: boolean; indent: number; spans: { start: number; length: number; }[]; childItems: [] } [] = [];
+ getNavigationBarItems(fileName: string): string;
// Returns a JSON encoded value of the type:
- // { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; minChar: number; limChar: number; } [] = [];
- getOutliningRegions(fileName: string): string;
+ // { textSpan: { start: number, length: number }; hintSpan: { start: number, length: number }; bannerText: string; autoCollapse: boolean } [] = [];
+ getOutliningSpans(fileName: string): string;
+
+ getTodoComments(fileName: string, todoCommentDescriptors: string): string;
getBraceMatchingAtPosition(fileName: string, position: number): string;
getIndentationAtPosition(fileName: string, position: number, options: string/*Services.EditorOptions*/): string;
- getFormattingEditsForRange(fileName: string, minChar: number, limChar: number, options: string/*Services.FormatCodeOptions*/): string;
- getFormattingEditsForDocument(fileName: string, minChar: number, limChar: number, options: string/*Services.FormatCodeOptions*/): string;
- getFormattingEditsOnPaste(fileName: string, minChar: number, limChar: number, options: string/*Services.FormatCodeOptions*/): string;
+ getFormattingEditsForRange(fileName: string, start: number, end: number, options: string/*Services.FormatCodeOptions*/): string;
+ getFormattingEditsForDocument(fileName: string, options: string/*Services.FormatCodeOptions*/): string;
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: string/*Services.FormatCodeOptions*/): string;
getEmitOutput(fileName: string): string;
@@ -456,7 +463,6 @@ module ts {
this.forwardJSONCall(
"refresh(" + throwOnError + ")",
() => {
- this.languageService.refresh();
return null;
});
}
@@ -469,8 +475,6 @@ module ts {
return null;
});
}
- /// SQUIGGLES
- ///
private static realizeDiagnostic(diagnostic: Diagnostic): { message: string; start: number; length: number; category: string; } {
return {
@@ -495,7 +499,7 @@ module ts {
public getSyntacticDiagnostics(fileName: string): string {
return this.forwardJSONCall(
- "getSyntacticDiagnostics(\"" + fileName + "\")",
+ "getSyntacticDiagnostics('" + fileName + "')",
() => {
var errors = this.languageService.getSyntacticDiagnostics(fileName);
return errors.map(LanguageServiceShimObject.realizeDiagnostic);
@@ -504,7 +508,7 @@ module ts {
public getSemanticDiagnostics(fileName: string): string {
return this.forwardJSONCall(
- "getSemanticDiagnostics(\"" + fileName + "\")",
+ "getSemanticDiagnostics('" + fileName + "')",
() => {
var errors = this.languageService.getSemanticDiagnostics(fileName);
return errors.map(LanguageServiceShimObject.realizeDiagnostic);
@@ -525,7 +529,7 @@ module ts {
/// in the active file.
public getTypeAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
- "getTypeAtPosition(\"" + fileName + "\", " + position + ")",
+ "getTypeAtPosition('" + fileName + "', " + position + ")",
() => {
var typeInfo = this.languageService.getTypeAtPosition(fileName, position);
return typeInfo;
@@ -537,7 +541,7 @@ module ts {
// in the active file.
public getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): string {
return this.forwardJSONCall(
- "getNameOrDottedNameSpan(\"" + fileName + "\", " + startPos + ", " + endPos + ")",
+ "getNameOrDottedNameSpan('" + fileName + "', " + startPos + ", " + endPos + ")",
() => {
var spanInfo = this.languageService.getNameOrDottedNameSpan(fileName, startPos, endPos);
return spanInfo;
@@ -548,7 +552,7 @@ module ts {
/// Computes span information of statement at the requested position in the active file.
public getBreakpointStatementAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
- "getBreakpointStatementAtPosition(\"" + fileName + "\", " + position + ")",
+ "getBreakpointStatementAtPosition('" + fileName + "', " + position + ")",
() => {
var spanInfo = this.languageService.getBreakpointStatementAtPosition(fileName, position);
return spanInfo;
@@ -556,32 +560,49 @@ module ts {
}
/// SIGNATUREHELP
- /// Computes a string representation of the signatures at the requested position
- /// in the active file.
- public getSignatureAtPosition(fileName: string, position: number): string {
+
+ public getSignatureHelpItems(fileName: string, position: number): string {
return this.forwardJSONCall(
- "getSignatureAtPosition(\"" + fileName + "\", " + position + ")",
+ "getSignatureHelpItems('" + fileName + "', " + position + ")",
() => {
- var signatureInfo = this.languageService.getSignatureAtPosition(fileName, position);
+ var signatureInfo = this.languageService.getSignatureHelpItems(fileName, position);
return signatureInfo;
});
}
+ public getSignatureHelpCurrentArgumentState(fileName: string, position: number, applicableSpanStart: number): string {
+ return this.forwardJSONCall(
+ "getSignatureHelpCurrentArgumentState('" + fileName + "', " + position + ", " + applicableSpanStart + ")",
+ () => {
+ var signatureInfo = this.languageService.getSignatureHelpItems(fileName, position);
+ return signatureInfo;
+ });
+ }
+
+
/// GOTO DEFINITION
/// Computes the definition location and file for the symbol
/// at the requested position.
public getDefinitionAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
- "getDefinitionAtPosition(\"" + fileName + "\", " + position + ")",
+ "getDefinitionAtPosition('" + fileName + "', " + position + ")",
() => {
return this.languageService.getDefinitionAtPosition(fileName, position);
});
}
+ public getRenameInfo(fileName: string, position: number): string {
+ return this.forwardJSONCall(
+ "getRenameInfo('" + fileName + "', " + position + ")",
+ () => {
+ return this.languageService.getRenameInfo(fileName, position);
+ });
+ }
+
/// GET BRACE MATCHING
public getBraceMatchingAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
- "getBraceMatchingAtPosition(\"" + fileName + "\", " + position + ")",
+ "getBraceMatchingAtPosition('" + fileName + "', " + position + ")",
() => {
var textRanges = this.languageService.getBraceMatchingAtPosition(fileName, position);
return textRanges;
@@ -591,7 +612,7 @@ module ts {
/// GET SMART INDENT
public getIndentationAtPosition(fileName: string, position: number, options: string /*Services.EditorOptions*/): string {
return this.forwardJSONCall(
- "getIndentationAtPosition(\"" + fileName + "\", " + position + ")",
+ "getIndentationAtPosition('" + fileName + "', " + position + ")",
() => {
var localOptions: EditorOptions = JSON.parse(options);
var columnOffset = this.languageService.getIndentationAtPosition(fileName, position, localOptions);
@@ -605,7 +626,7 @@ module ts {
/// Each reference is a "fileindex min lim" sub-string.
public getReferencesAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
- "getReferencesAtPosition(\"" + fileName + "\", " + position + ")",
+ "getReferencesAtPosition('" + fileName + "', " + position + ")",
() => {
return this.languageService.getReferencesAtPosition(fileName, position);
});
@@ -613,7 +634,7 @@ module ts {
public getOccurrencesAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
- "getOccurrencesAtPosition(\"" + fileName + "\", " + position + ")",
+ "getOccurrencesAtPosition('" + fileName + "', " + position + ")",
() => {
return this.languageService.getOccurrencesAtPosition(fileName, position);
});
@@ -622,7 +643,7 @@ module ts {
/// GET IMPLEMENTORS
public getImplementorsAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
- "getImplementorsAtPosition(\"" + fileName + "\", " + position + ")",
+ "getImplementorsAtPosition('" + fileName + "', " + position + ")",
() => {
return this.languageService.getImplementorsAtPosition(fileName, position);
});
@@ -635,7 +656,7 @@ module ts {
/// list if requested.
public getCompletionsAtPosition(fileName: string, position: number, isMemberCompletion: boolean) {
return this.forwardJSONCall(
- "getCompletionsAtPosition(\"" + fileName + "\", " + position + ", " + isMemberCompletion + ")",
+ "getCompletionsAtPosition('" + fileName + "', " + position + ", " + isMemberCompletion + ")",
() => {
var completion = this.languageService.getCompletionsAtPosition(fileName, position, isMemberCompletion);
return completion;
@@ -645,52 +666,38 @@ module ts {
/// Get a string based representation of a completion list entry details
public getCompletionEntryDetails(fileName: string, position: number, entryName: string) {
return this.forwardJSONCall(
- "getCompletionEntryDetails(\"" + fileName + "\", " + position + ", " + entryName + ")",
+ "getCompletionEntryDetails('" + fileName + "', " + position + ", " + entryName + ")",
() => {
var details = this.languageService.getCompletionEntryDetails(fileName, position, entryName);
return details;
});
}
- /// FORMAT SELECTION
- public getFormattingEditsForRange(fileName: string, minChar: number, limChar: number, options: string/*Services.FormatCodeOptions*/): string {
+ public getFormattingEditsForRange(fileName: string, start: number, end: number, options: string/*Services.FormatCodeOptions*/): string {
return this.forwardJSONCall(
- "getFormattingEditsForRange(\"" + fileName + "\", " + minChar + ", " + limChar + ")",
+ "getFormattingEditsForRange('" + fileName + "', " + start + ", " + end + ")",
() => {
- var localOptions: FormatCodeOptions = JSON.parse(options);
- var edits = this.languageService.getFormattingEditsForRange(fileName, minChar, limChar, localOptions);
+ var localOptions: ts.FormatCodeOptions = JSON.parse(options);
+ var edits = this.languageService.getFormattingEditsForRange(fileName, start, end, localOptions);
return edits;
});
}
- /// FORMAT DOCUMENT
- public getFormattingEditsForDocument(fileName: string, minChar: number, limChar: number, options: string/*Services.FormatCodeOptions*/): string {
+ public getFormattingEditsForDocument(fileName: string, options: string/*Services.FormatCodeOptions*/): string {
return this.forwardJSONCall(
- "getFormattingEditsForDocument(\"" + fileName + "\", " + minChar + ", " + limChar + ")",
+ "getFormattingEditsForDocument('" + fileName + "')",
() => {
- var localOptions: FormatCodeOptions = JSON.parse(options);
- var edits = this.languageService.getFormattingEditsForDocument(fileName, minChar, limChar, localOptions);
+ var localOptions: ts.FormatCodeOptions = JSON.parse(options);
+ var edits = this.languageService.getFormattingEditsForDocument(fileName, localOptions);
return edits;
});
}
- /// FORMAT ON PASTE
- public getFormattingEditsOnPaste(fileName: string, minChar: number, limChar: number, options: string/*Services.FormatCodeOptions*/): string {
- return this.forwardJSONCall(
- "getFormattingEditsOnPaste(\"" + fileName + "\", " + minChar + ", " + limChar + ")",
- () => {
- var localOptions: FormatCodeOptions = JSON.parse(options);
- var edits = this.languageService.getFormattingEditsOnPaste(fileName, minChar, limChar, localOptions);
- return edits;
- });
- }
-
- /// FORMAT
public getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: string/*Services.FormatCodeOptions*/): string {
return this.forwardJSONCall(
- "getFormattingEditsAfterKeystroke(\"" + fileName + "\", " + position + ", \"" + key + "\")",
+ "getFormattingEditsAfterKeystroke('" + fileName + "', " + position + ", '" + key + "')",
() => {
- var localOptions: FormatCodeOptions = JSON.parse(options);
+ var localOptions: ts.FormatCodeOptions = JSON.parse(options);
var edits = this.languageService.getFormattingEditsAfterKeystroke(fileName, position, key, localOptions);
return edits;
});
@@ -700,83 +707,49 @@ module ts {
/// Return a list of symbols that are interesting to navigate to
public getNavigateToItems(searchValue: string): string {
return this.forwardJSONCall(
- "getNavigateToItems(\"" + searchValue + "\")",
+ "getNavigateToItems('" + searchValue + "')",
() => {
var items = this.languageService.getNavigateToItems(searchValue);
- var result = this._navigateToItemsToString(items);
- return result;
+ return items;
});
}
- // GET SCRIPT LEXICAL STRUCTURE
- //
- public getScriptLexicalStructure(fileName: string): string {
+ public getNavigationBarItems(fileName: string): string {
return this.forwardJSONCall(
- "getScriptLexicalStructure(\"" + fileName + "\")",
+ "getNavigationBarItems('" + fileName + "')",
() => {
- var items = this.languageService.getScriptLexicalStructure(fileName);
- var result = this._navigateToItemsToString(items);
- return result;
+ var items = this.languageService.getNavigationBarItems(fileName);
+ return items;
});
}
- // GET OUTLINING REGIONS
- //
- public getOutliningRegions(fileName: string): string {
+ public getOutliningSpans(fileName: string): string {
return this.forwardJSONCall(
- "getOutliningRegions(\"" + fileName + "\")",
+ "getOutliningSpans('" + fileName + "')",
() => {
- var items = this.languageService.getOutliningRegions(fileName);
- // return just the part of data that language service v2 can understand
- // language service v2 will use the entire OutliningSpan
- var spans = map(items, i => i.textSpan);
- return spans;
+ var items = this.languageService.getOutliningSpans(fileName);
+ return items;
+ });
+ }
+
+ public getTodoComments(fileName: string, descriptors: string): string {
+ return this.forwardJSONCall(
+ "getTodoComments('" + fileName + "')",
+ () => {
+ var items = this.languageService.getTodoComments(fileName, JSON.parse(descriptors));
+ return items;
});
}
/// Emit
public getEmitOutput(fileName: string): string {
return this.forwardJSONCall(
- "getEmitOutput(\"" + fileName + "\")",
+ "getEmitOutput('" + fileName + "')",
() => {
var output = this.languageService.getEmitOutput(fileName);
return output;
});
}
-
- private _navigateToItemsToString(items: NavigateToItem[]): any {
- var result: {
- name: string;
- kind: string;
- kindModifiers: string;
- containerName: string;
- containerKind: string;
- matchKind: string;
- fileName: string;
- minChar: number;
- limChar: number;
- additionalSpans?: { start: number; end: number; }[];
- }[] = [];
-
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
-
- result.push({
- name: item.name,
- kind: item.kind,
- kindModifiers: item.kindModifiers,
- containerName: item.containerName,
- containerKind: item.containerKind,
- matchKind: item.matchKind,
- fileName: item.fileName,
- minChar: item.minChar,
- limChar: item.limChar,
- additionalSpans: item.additionalSpans ? item.additionalSpans.map(i => { return { start: i.minChar, end: i.limChar }; }) : undefined
- });
- }
-
- return result;
- }
}
class ClassifierShimObject extends ShimBase implements ClassifierShim {
@@ -815,7 +788,7 @@ module ts {
///
public getPreProcessedFileInfo(fileName: string, sourceText: TypeScript.IScriptSnapshot): string {
return this.forwardJSONCall(
- "getPreProcessedFileInfo(\"" + fileName + "\")",
+ "getPreProcessedFileInfo('" + fileName + "')",
() => {
var result = TypeScript.preProcessFile(fileName, sourceText);
return result;