Merge branch 'master' into printDiagnosticCodes
This commit is contained in:
commit
48c6bdb2aa
|
@ -188,14 +188,11 @@ module ts {
|
|||
|
||||
export var localizedDiagnosticMessages: Map<string> = undefined;
|
||||
|
||||
function getLocaleSpecificMessage(message: string) {
|
||||
export function getLocaleSpecificMessage(message: string) {
|
||||
if (ts.localizedDiagnosticMessages) {
|
||||
message = localizedDiagnosticMessages[message];
|
||||
}
|
||||
|
||||
/* Check to see that we got an actual value back. */
|
||||
Debug.assert(message, "Diagnostic message does not exist in locale map.");
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ module ts {
|
|||
Import_declarations_in_an_internal_module_cannot_reference_an_external_module: { code: 1147, category: DiagnosticCategory.Error, key: "Import declarations in an internal module cannot reference an external module." },
|
||||
Cannot_compile_external_modules_unless_the_module_flag_is_provided: { code: 1148, category: DiagnosticCategory.Error, key: "Cannot compile external modules unless the '--module' flag is provided." },
|
||||
Filename_0_differs_from_already_included_filename_1_only_in_casing: { code: 1149, category: DiagnosticCategory.Error, key: "Filename '{0}' differs from already included filename '{1}' only in casing" },
|
||||
new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead: { code: 2068, category: DiagnosticCategory.Error, key: "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead." },
|
||||
new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead: { code: 1150, category: DiagnosticCategory.Error, key: "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead." },
|
||||
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
|
||||
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
|
||||
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
|
||||
|
@ -389,5 +389,6 @@ module ts {
|
|||
Object_literal_s_property_0_implicitly_has_an_1_type: { code: 7018, category: DiagnosticCategory.Error, key: "Object literal's property '{0}' implicitly has an '{1}' type." },
|
||||
Rest_parameter_0_implicitly_has_an_any_type: { code: 7019, category: DiagnosticCategory.Error, key: "Rest parameter '{0}' implicitly has an 'any[]' type." },
|
||||
Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7020, category: DiagnosticCategory.Error, key: "Call signature, which lacks return-type annotation, implicitly has an 'any' return type." },
|
||||
You_cannot_rename_this_element: { code: 8000, category: DiagnosticCategory.Error, key: "You cannot rename this element." },
|
||||
};
|
||||
}
|
|
@ -1355,7 +1355,6 @@
|
|||
"category": "Error",
|
||||
"code": 5039
|
||||
},
|
||||
|
||||
"Concatenate and emit output to single file.": {
|
||||
"category": "Message",
|
||||
"code": 6001
|
||||
|
@ -1552,5 +1551,9 @@
|
|||
"Call signature, which lacks return-type annotation, implicitly has an 'any' return type.": {
|
||||
"category": "Error",
|
||||
"code": 7020
|
||||
},
|
||||
"You cannot rename this element.": {
|
||||
"category": "Error",
|
||||
"code": 8000
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ module ts {
|
|||
export function getNodeConstructor(kind: SyntaxKind): new () => Node {
|
||||
return nodeConstructors[kind] || (nodeConstructors[kind] = objectAllocator.getNodeConstructor(kind));
|
||||
}
|
||||
|
||||
|
||||
function createRootNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags): Node {
|
||||
var node = new (getNodeConstructor(kind))();
|
||||
node.pos = pos;
|
||||
|
@ -443,7 +443,7 @@ module ts {
|
|||
nodeIsNestedInLabel(label: Identifier, requireIterationStatement: boolean, stopAtFunctionBoundary: boolean): ControlBlockContext;
|
||||
}
|
||||
|
||||
export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, version: number = 0, isOpen: boolean = false): SourceFile {
|
||||
export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, version: string, isOpen: boolean = false): SourceFile {
|
||||
var file: SourceFile;
|
||||
var scanner: Scanner;
|
||||
var token: SyntaxKind;
|
||||
|
|
|
@ -147,7 +147,7 @@ module ts {
|
|||
}
|
||||
text = "";
|
||||
}
|
||||
return text !== undefined ? createSourceFile(filename, text, languageVersion) : undefined;
|
||||
return text !== undefined ? createSourceFile(filename, text, languageVersion, /*version:*/ "0") : undefined;
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
|
||||
|
|
|
@ -535,7 +535,7 @@ module ts {
|
|||
identifierCount: number;
|
||||
symbolCount: number;
|
||||
isOpen: boolean;
|
||||
version: number;
|
||||
version: string;
|
||||
languageVersion: ScriptTarget;
|
||||
}
|
||||
|
||||
|
|
|
@ -183,19 +183,40 @@ class CompilerBaselineRunner extends RunnerBase {
|
|||
|
||||
// if the .d.ts is non-empty, confirm it compiles correctly as well
|
||||
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) {
|
||||
function getDtsFile(file: { unitName: string; content: string }) {
|
||||
function addDtsFile(file: { unitName: string; content: string }, dtsFiles: { unitName: string; content: string }[]) {
|
||||
if (Harness.Compiler.isDTS(file.unitName)) {
|
||||
return file;
|
||||
} else {
|
||||
var declFile = ts.forEach(result.declFilesCode,
|
||||
declFile => declFile.fileName === (file.unitName.substr(0, file.unitName.length - ".ts".length) + ".d.ts")
|
||||
dtsFiles.push(file);
|
||||
}
|
||||
else {
|
||||
var declFile = findResultCodeFile(file.unitName);
|
||||
// Look if there is --out file corresponding to this ts file
|
||||
if (!declFile && options.out) {
|
||||
declFile = findResultCodeFile(options.out);
|
||||
if (!declFile || findUnit(declFile.fileName, declToBeCompiled) ||
|
||||
findUnit(declFile.fileName, declOtherFiles)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (declFile) {
|
||||
dtsFiles.push({ unitName: declFile.fileName, content: declFile.code });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function findResultCodeFile(fileName: string) {
|
||||
return ts.forEach(result.declFilesCode,
|
||||
declFile => declFile.fileName === (fileName.substr(0, fileName.length - ".ts".length) + ".d.ts")
|
||||
? declFile : undefined);
|
||||
return { unitName: declFile.fileName, content: declFile.code };
|
||||
}
|
||||
|
||||
function findUnit(fileName: string, units: { unitName: string; content: string }[]) {
|
||||
return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined);
|
||||
}
|
||||
}
|
||||
|
||||
ts.forEach(toBeCompiled, file => { declToBeCompiled.push(getDtsFile(file)); });
|
||||
ts.forEach(otherFiles, file => { declOtherFiles.push(getDtsFile(file)); });
|
||||
ts.forEach(toBeCompiled, file => addDtsFile(file, declToBeCompiled));
|
||||
ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles));
|
||||
harnessCompiler.compileFiles(declToBeCompiled, declOtherFiles, function (compileResult) {
|
||||
declResult = compileResult;
|
||||
}, function (settings) {
|
||||
|
|
|
@ -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('<InvokeSignatureHelp />');
|
||||
this.scenarioActions.push('<VerifySignatureHelpOverloadCountEquals Count="' + expected + '" />');
|
||||
|
||||
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('<FormatDocument />');
|
||||
|
||||
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);
|
||||
|
@ -1425,6 +1410,25 @@ module FourSlash {
|
|||
}
|
||||
}
|
||||
|
||||
public verifyTodoComments(descriptors: string[], spans: TextSpan[]) {
|
||||
var actual = this.languageService.getTodoComments(this.activeFile.fileName,
|
||||
descriptors.map(d => new ts.TodoCommentDescriptor(d, 0)));
|
||||
|
||||
if (actual.length !== spans.length) {
|
||||
throw new Error('verifyTodoComments failed - expected total spans to be ' + spans.length + ', but was ' + actual.length);
|
||||
}
|
||||
|
||||
for (var i = 0; i < spans.length; i++) {
|
||||
var expectedSpan = spans[i];
|
||||
var actualComment = actual[i];
|
||||
var actualCommentSpan = new TypeScript.TextSpan(actualComment.position, actualComment.message.length);
|
||||
|
||||
if (expectedSpan.start !== actualCommentSpan.start() || expectedSpan.end !== actualCommentSpan.end()) {
|
||||
throw new Error('verifyOutliningSpans failed - span ' + (i + 1) + ' expected: (' + expectedSpan.start + ',' + expectedSpan.end + '), actual: (' + actualCommentSpan.start() + ',' + actualCommentSpan.end() + ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public verifyMatchingBracePosition(bracePosition: number, expectedMatchPosition: number) {
|
||||
this.taoInvalidReason = 'verifyMatchingBracePosition NYI';
|
||||
|
||||
|
@ -1584,70 +1588,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 +1658,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 +1684,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 + '.');
|
||||
}
|
||||
|
@ -1895,11 +1890,11 @@ module FourSlash {
|
|||
var result = '';
|
||||
var fourslashFilename = 'fourslash.ts';
|
||||
var tsFn = 'tests/cases/fourslash/' + fourslashFilename;
|
||||
fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), ts.ScriptTarget.ES5, /*version*/ 0, /*isOpen*/ false);
|
||||
fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), ts.ScriptTarget.ES5, /*version*/ "0", /*isOpen*/ false);
|
||||
|
||||
var files: { [filename: string]: ts.SourceFile; } = {};
|
||||
files[ts.getCanonicalFileName(fourslashFilename)] = fourslashSourceFile;
|
||||
files[ts.getCanonicalFileName(fileName)] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5, /*version*/ 0, /*isOpen*/ false);
|
||||
files[ts.getCanonicalFileName(fileName)] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5, /*version*/ "0", /*isOpen*/ false);
|
||||
files[ts.getCanonicalFileName(Harness.Compiler.defaultLibFileName)] = Harness.Compiler.defaultLibSourceFile;
|
||||
|
||||
var host = Harness.Compiler.createCompilerHost(files, (fn, contents) => result = contents);
|
||||
|
|
|
@ -532,7 +532,7 @@ module Harness {
|
|||
}
|
||||
|
||||
export var defaultLibFileName = 'lib.d.ts';
|
||||
export var defaultLibSourceFile = ts.createSourceFile(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.ES5);
|
||||
export var defaultLibSourceFile = ts.createSourceFile(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.ES5, /*version:*/ "0");
|
||||
|
||||
export function createCompilerHost(filemap: { [filename: string]: ts.SourceFile; }, writeFile: (fn: string, contents: string, writeByteOrderMark:boolean) => void): ts.CompilerHost {
|
||||
return {
|
||||
|
@ -729,7 +729,7 @@ module Harness {
|
|||
var filemap: { [name: string]: ts.SourceFile; } = {};
|
||||
var register = (file: { unitName: string; content: string; }) => {
|
||||
var filename = Path.switchToForwardSlashes(file.unitName);
|
||||
filemap[ts.getCanonicalFileName(filename)] = ts.createSourceFile(filename, file.content, options.target);
|
||||
filemap[ts.getCanonicalFileName(filename)] = ts.createSourceFile(filename, file.content, options.target, /*version:*/ "0");
|
||||
};
|
||||
inputFiles.forEach(register);
|
||||
otherFiles.forEach(register);
|
||||
|
|
|
@ -80,8 +80,9 @@ module Harness.LanguageService {
|
|||
return JSON.stringify(this.lineMap.lineStarts());
|
||||
}
|
||||
|
||||
public getTextChangeRangeSinceVersion(scriptVersion: number): string {
|
||||
var range = this.scriptInfo.getTextChangeRangeBetweenVersions(scriptVersion, this.version);
|
||||
public getChangeRange(oldScript: ts.ScriptSnapshotShim): string {
|
||||
var oldShim = <ScriptSnapshotShim>oldScript;
|
||||
var range = this.scriptInfo.getTextChangeRangeBetweenVersions(oldShim.version, this.version);
|
||||
if (range === null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -101,50 +102,14 @@ module Harness.LanguageService {
|
|||
}
|
||||
}
|
||||
|
||||
class ScriptSnapshotShimAdapter implements TypeScript.IScriptSnapshot {
|
||||
private lineStartPositions: number[] = null;
|
||||
constructor(private scriptSnapshotShim: ts.ScriptSnapshotShim) {}
|
||||
getText(start: number, end: number): string {return this.scriptSnapshotShim.getText(start, end);}
|
||||
getLength(): number {return this.scriptSnapshotShim.getLength();}
|
||||
getLineStartPositions(): number[] { return JSON.parse(this.scriptSnapshotShim.getLineStartPositions()); }
|
||||
getTextChangeRangeSinceVersion(scriptVersion: number): TypeScript.TextChangeRange {
|
||||
var encoded = this.scriptSnapshotShim.getTextChangeRangeSinceVersion(scriptVersion);
|
||||
if (encoded == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var decoded: { span: { start: number; length: number; }; newLength: number; } = JSON.parse(encoded);
|
||||
return new TypeScript.TextChangeRange(
|
||||
new TypeScript.TextSpan(decoded.span.start, decoded.span.length), decoded.newLength);
|
||||
}
|
||||
}
|
||||
|
||||
class LanguageServiceShimHostAdapter implements ts.LanguageServiceHost {
|
||||
constructor(private shimHost: ts.LanguageServiceShimHost) { }
|
||||
information(): boolean { return this.shimHost.information(); }
|
||||
debug(): boolean { return this.shimHost.debug(); }
|
||||
warning(): boolean { return this.shimHost.warning();}
|
||||
error(): boolean { return this.shimHost.error(); }
|
||||
fatal(): boolean { return this.shimHost.fatal(); }
|
||||
log(s: string): void { this.shimHost.log(s); }
|
||||
getCompilationSettings(): ts.CompilerOptions { return JSON.parse(this.shimHost.getCompilationSettings()); }
|
||||
getScriptFileNames(): string[] { return JSON.parse(this.shimHost.getScriptFileNames());}
|
||||
getScriptSnapshot(fileName: string): TypeScript.IScriptSnapshot { return new ScriptSnapshotShimAdapter(this.shimHost.getScriptSnapshot(fileName));}
|
||||
getScriptVersion(fileName: string): number { return this.shimHost.getScriptVersion(fileName);}
|
||||
getScriptIsOpen(fileName: string): boolean { return this.shimHost.getScriptIsOpen(fileName); }
|
||||
getLocalizedDiagnosticMessages(): any { JSON.parse(this.shimHost.getLocalizedDiagnosticMessages());}
|
||||
getCancellationToken(): ts.CancellationToken { return this.shimHost.getCancellationToken(); }
|
||||
}
|
||||
|
||||
export class NonCachingDocumentRegistry implements ts.DocumentRegistry {
|
||||
|
||||
public static Instance: ts.DocumentRegistry = new NonCachingDocumentRegistry();
|
||||
|
||||
public acquireDocument(
|
||||
fileName: string,
|
||||
compilationSettings: ts.CompilerOptions,
|
||||
scriptSnapshot: TypeScript.IScriptSnapshot,
|
||||
version: number,
|
||||
version: string,
|
||||
isOpen: boolean): ts.SourceFile {
|
||||
return ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, version, isOpen);
|
||||
}
|
||||
|
@ -154,7 +119,7 @@ module Harness.LanguageService {
|
|||
fileName: string,
|
||||
compilationSettings: ts.CompilerOptions,
|
||||
scriptSnapshot: TypeScript.IScriptSnapshot,
|
||||
version: number,
|
||||
version: string,
|
||||
isOpen: boolean,
|
||||
textChangeRange: TypeScript.TextChangeRange
|
||||
): ts.SourceFile {
|
||||
|
@ -251,8 +216,8 @@ module Harness.LanguageService {
|
|||
return new ScriptSnapshotShim(this.getScriptInfo(fileName));
|
||||
}
|
||||
|
||||
public getScriptVersion(fileName: string): number {
|
||||
return this.getScriptInfo(fileName).version;
|
||||
public getScriptVersion(fileName: string): string {
|
||||
return this.getScriptInfo(fileName).version.toString();
|
||||
}
|
||||
|
||||
public getScriptIsOpen(fileName: string): boolean {
|
||||
|
@ -316,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);
|
||||
|
@ -345,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 });
|
||||
}
|
||||
|
@ -372,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;
|
||||
|
@ -391,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) {
|
||||
|
@ -400,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;
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ class ProjectRunner extends RunnerBase {
|
|||
else {
|
||||
var text = getSourceFileText(filename);
|
||||
if (text !== undefined) {
|
||||
sourceFile = ts.createSourceFile(filename, text, languageVersion);
|
||||
sourceFile = ts.createSourceFile(filename, text, languageVersion, /*version:*/ "0");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,16 +4,13 @@
|
|||
///<reference path='references.ts' />
|
||||
|
||||
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 = <TypeScript.BinaryExpressionSyntax>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(<TypeScript.ISyntaxNode>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(<ISyntaxNode>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 = <TypeScript.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 = <TypeScript.IfStatementSyntax>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 = <TypeScript.ElseClauseSyntax>elseClauseNode;
|
||||
return this.breakpointSpanOf(elseClause.statement);
|
||||
}
|
||||
|
||||
private breakpointSpanOfForInStatement(forInStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
|
||||
private breakpointSpanOfForInStatement(forInStatementNode: TypeScript.ISyntaxNode): TextSpan {
|
||||
var forInStatement = <TypeScript.ForInStatementSyntax>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 = <TypeScript.ForStatementSyntax>forStatementNode;
|
||||
return this.breakpointSpanOf(forStatement.variableDeclaration
|
||||
? <TypeScript.ISyntaxElement>forStatement.variableDeclaration
|
||||
: forStatement.initializer);
|
||||
}
|
||||
|
||||
private breakpointSpanOfWhileStatement(whileStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
|
||||
private breakpointSpanOfWhileStatement(whileStatementNode: TypeScript.ISyntaxNode): TextSpan {
|
||||
var whileStatement = <TypeScript.WhileStatementSyntax>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 = <TypeScript.DoStatementSyntax>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 = <TypeScript.SwitchStatementSyntax>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 = <TypeScript.SwitchStatementSyntax>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 = <TypeScript.SwitchStatementSyntax>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 = <TypeScript.CaseSwitchClauseSyntax>caseClauseNode;
|
||||
return this.breakpointSpanOfFirstChildOfSyntaxList(caseSwitchClause.statements);
|
||||
}
|
||||
|
||||
private breakpointSpanOfDefaultSwitchClause(defaultSwithClauseNode: TypeScript.ISyntaxNode): ts.SpanInfo {
|
||||
private breakpointSpanOfDefaultSwitchClause(defaultSwithClauseNode: TypeScript.ISyntaxNode): TextSpan {
|
||||
var defaultSwitchClause = <TypeScript.DefaultSwitchClauseSyntax>defaultSwithClauseNode;
|
||||
return this.breakpointSpanOfFirstChildOfSyntaxList(defaultSwitchClause.statements);
|
||||
}
|
||||
|
||||
private breakpointSpanOfWithStatement(withStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
|
||||
private breakpointSpanOfWithStatement(withStatementNode: TypeScript.ISyntaxNode): TextSpan {
|
||||
var withStatement = <TypeScript.WithStatementSyntax>withStatementNode;
|
||||
return this.breakpointSpanOf(withStatement.statement);
|
||||
}
|
||||
|
||||
private breakpointSpanOfTryStatement(tryStatementNode: TypeScript.ISyntaxNode): ts.SpanInfo {
|
||||
private breakpointSpanOfTryStatement(tryStatementNode: TypeScript.ISyntaxNode): TextSpan {
|
||||
var tryStatement = <TypeScript.TryStatementSyntax>tryStatementNode;
|
||||
return this.breakpointSpanOfFirstStatementInBlock(<TypeScript.ISyntaxNode>tryStatement.block);
|
||||
}
|
||||
|
||||
private breakpointSpanOfCatchClause(catchClauseNode: TypeScript.ISyntaxNode): ts.SpanInfo {
|
||||
private breakpointSpanOfCatchClause(catchClauseNode: TypeScript.ISyntaxNode): TextSpan {
|
||||
var catchClause = <TypeScript.CatchClauseSyntax>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 = <TypeScript.FinallyClauseSyntax>finallyClauseNode;
|
||||
return this.breakpointSpanOfFirstStatementInBlock(<TypeScript.ISyntaxNode>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;
|
||||
|
|
|
@ -17,31 +17,11 @@
|
|||
|
||||
module TypeScript {
|
||||
export interface Logger {
|
||||
information(): boolean;
|
||||
debug(): boolean;
|
||||
warning(): boolean;
|
||||
error(): boolean;
|
||||
fatal(): boolean;
|
||||
log(s: string): void;
|
||||
}
|
||||
|
||||
export class NullLogger implements Logger {
|
||||
public information(): boolean { return false; }
|
||||
public debug(): boolean { return false; }
|
||||
public warning(): boolean { return false; }
|
||||
public error(): boolean { return false; }
|
||||
public fatal(): boolean { return false; }
|
||||
public log(s: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function timeFunction(logger: Logger, funcDescription: string, func: () => any): any {
|
||||
var start = (new Date()).getTime();
|
||||
var result = func();
|
||||
var end = (new Date()).getTime();
|
||||
if (logger.information()) {
|
||||
logger.log(funcDescription + " completed in " + (end - start) + " msec");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -40,8 +40,8 @@ module TypeScript.Services.Formatting {
|
|||
|
||||
public ensureUpToDate(options: ts.FormatCodeOptions) {
|
||||
if (this.options == null || !ts.compareDataObjects(this.options, options)) {
|
||||
var activeRules: Rule[] = TypeScript.timeFunction(this.logger, "RulesProvider: createActiveRules()", () => { return this.createActiveRules(options); });
|
||||
var rulesMap: RulesMap = TypeScript.timeFunction(this.logger, "RulesProvider: RulesMap.create()", () => { return RulesMap.create(activeRules); });
|
||||
var activeRules = this.createActiveRules(options);
|
||||
var rulesMap = RulesMap.create(activeRules);
|
||||
|
||||
this.activeRules = activeRules;
|
||||
this.rulesMap = rulesMap;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -1,121 +1,22 @@
|
|||
|
||||
///<reference path='references.ts' />
|
||||
|
||||
module TypeScript.Services {
|
||||
interface LexicalScope {
|
||||
items: ts.Map<ts.NavigateToItem>;
|
||||
itemNames: string[];
|
||||
childScopes: ts.Map<LexicalScope>;
|
||||
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<ts.NavigateToItem>(),
|
||||
childScopes: TypeScript.createIntrinsicsObject<LexicalScope>(),
|
||||
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 = <ISyntaxNode>nodes[i];
|
||||
|
||||
if (node.kind() === SyntaxKind.FunctionDeclaration) {
|
||||
childNodes.push(node);
|
||||
}
|
||||
else if (node.kind() === SyntaxKind.VariableStatement) {
|
||||
var variableDeclaration = (<VariableStatementSyntax>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 = <ModuleDeclarationSyntax>node;
|
||||
topLevelNodes.push(node);
|
||||
this.addTopLevelNodes(moduleDeclaration.moduleElements, topLevelNodes);
|
||||
break;
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
var functionDeclaration = <FunctionDeclarationSyntax>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<ts.NavigationBarItem>();
|
||||
|
||||
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 = <ParameterSyntax>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 = <MemberFunctionDeclarationSyntax>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 = <GetAccessorSyntax>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 = <SetAccessorSyntax>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 = <IndexSignatureSyntax>node;
|
||||
return new ts.NavigationBarItem("[]", ts.ScriptElementKind.indexSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
|
||||
|
||||
case SyntaxKind.EnumElement:
|
||||
var enumElement = <EnumElementSyntax>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 = <CallSignatureSyntax>node;
|
||||
return new ts.NavigationBarItem("()", ts.ScriptElementKind.callSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
|
||||
|
||||
case SyntaxKind.ConstructSignature:
|
||||
var constructSignature = <ConstructSignatureSyntax>node;
|
||||
return new ts.NavigationBarItem("new()", ts.ScriptElementKind.constructSignatureElement, ts.ScriptElementKindModifier.none, [TextSpan.fromBounds(start(node), end(node))]);
|
||||
|
||||
case SyntaxKind.MethodSignature:
|
||||
var methodSignature = <MethodSignatureSyntax>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 = <PropertySignatureSyntax>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 = <FunctionDeclarationSyntax>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 = <MemberVariableDeclarationSyntax>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 = <VariableDeclaratorSyntax>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 = <ConstructorDeclarationSyntax>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(<SourceUnitSyntax>node);
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return this.createClassItem(<ClassDeclarationSyntax>node);
|
||||
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
return this.createEnumItem(<EnumDeclarationSyntax>node);
|
||||
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
return this.createIterfaceItem(<InterfaceDeclarationSyntax>node);
|
||||
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return this.createModuleItem(<ModuleDeclarationSyntax>node);
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return this.createFunctionItem(<FunctionDeclarationSyntax>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<ISyntaxToken>(), 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 = <ParameterSyntax>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("<global>",
|
||||
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 = <ConstructorDeclarationSyntax>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
|
||||
? (<ISyntaxNode[]>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
|
||||
? (<MemberVariableDeclarationSyntax>node.parent).modifiers
|
||||
: TypeScript.Syntax.emptyList<ISyntaxToken>();
|
||||
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<ISyntaxToken>(), ts.ScriptElementKind.indexSignatureElement, "[]");
|
||||
|
||||
// No need to descend into an index signature;
|
||||
}
|
||||
|
||||
public visitEnumElement(node: TypeScript.EnumElementSyntax): void {
|
||||
this.createItem(node, TypeScript.Syntax.emptyList<ISyntaxToken>(), 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<ISyntaxToken>(), ts.ScriptElementKind.callSignatureElement, "()");
|
||||
|
||||
// No need to descend into a call signature;
|
||||
}
|
||||
|
||||
public visitConstructSignature(node: TypeScript.ConstructSignatureSyntax): void {
|
||||
this.createItem(node, TypeScript.Syntax.emptyList<ISyntaxToken>(), ts.ScriptElementKind.constructSignatureElement, "new()");
|
||||
|
||||
// No need to descend into a construct signature;
|
||||
}
|
||||
|
||||
public visitMethodSignature(node: TypeScript.MethodSignatureSyntax): void {
|
||||
this.createItem(node, TypeScript.Syntax.emptyList<ISyntaxToken>(), 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<ISyntaxToken>(), 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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,7 +26,6 @@
|
|||
/// <reference path='compiler\pathUtils.ts' />
|
||||
|
||||
module ts {
|
||||
|
||||
export interface Node {
|
||||
getSourceFile(): SourceFile;
|
||||
getChildCount(): number;
|
||||
|
@ -72,7 +71,8 @@ module ts {
|
|||
getSourceUnit(): TypeScript.SourceUnitSyntax;
|
||||
getSyntaxTree(): TypeScript.SyntaxTree;
|
||||
getBloomFilter(): TypeScript.BloomFilter;
|
||||
update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile;
|
||||
getScriptSnapshot(): TypeScript.IScriptSnapshot;
|
||||
update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile;
|
||||
}
|
||||
|
||||
var scanner: Scanner = createScanner(ScriptTarget.ES5);
|
||||
|
@ -321,7 +321,7 @@ module ts {
|
|||
public identifierCount: number;
|
||||
public symbolCount: number;
|
||||
public statements: NodeArray<Statement>;
|
||||
public version: number;
|
||||
public version: string;
|
||||
public isOpen: boolean;
|
||||
public languageVersion: ScriptTarget;
|
||||
|
||||
|
@ -334,6 +334,10 @@ module ts {
|
|||
return this.getSyntaxTree().sourceUnit();
|
||||
}
|
||||
|
||||
public getScriptSnapshot(): TypeScript.IScriptSnapshot {
|
||||
return this.scriptSnapshot;
|
||||
}
|
||||
|
||||
public getLineMap(): TypeScript.LineMap {
|
||||
return this.getSyntaxTree().lineMap();
|
||||
}
|
||||
|
@ -385,7 +389,7 @@ module ts {
|
|||
return this.bloomFilter;
|
||||
}
|
||||
|
||||
public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: number, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile {
|
||||
public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile {
|
||||
// See if we are currently holding onto a syntax tree. We may not be because we're
|
||||
// either a closed file, or we've just been lazy and haven't had to create the syntax
|
||||
// tree yet. Access the field instead of the method so we don't accidently realize
|
||||
|
@ -420,7 +424,7 @@ module ts {
|
|||
return SourceFileObject.createSourceFileObject(this.filename, scriptSnapshot, this.languageVersion, version, isOpen, newSyntaxTree);
|
||||
}
|
||||
|
||||
public static createSourceFileObject(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, languageVersion: ScriptTarget, version: number, isOpen: boolean, syntaxTree?: TypeScript.SyntaxTree) {
|
||||
public static createSourceFileObject(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, languageVersion: ScriptTarget, version: string, isOpen: boolean, syntaxTree?: TypeScript.SyntaxTree) {
|
||||
var newSourceFile = <SourceFileObject><any>createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, version, isOpen);
|
||||
newSourceFile.scriptSnapshot = scriptSnapshot;
|
||||
newSourceFile.syntaxTree = syntaxTree;
|
||||
|
@ -429,11 +433,6 @@ module ts {
|
|||
}
|
||||
|
||||
export interface Logger {
|
||||
information(): boolean;
|
||||
debug(): boolean;
|
||||
warning(): boolean;
|
||||
error(): boolean;
|
||||
fatal(): boolean;
|
||||
log(s: string): void;
|
||||
}
|
||||
|
||||
|
@ -443,7 +442,7 @@ module ts {
|
|||
export interface LanguageServiceHost extends Logger {
|
||||
getCompilationSettings(): CompilerOptions;
|
||||
getScriptFileNames(): string[];
|
||||
getScriptVersion(fileName: string): number;
|
||||
getScriptVersion(fileName: string): string;
|
||||
getScriptIsOpen(fileName: string): boolean;
|
||||
getScriptSnapshot(fileName: string): TypeScript.IScriptSnapshot;
|
||||
getLocalizedDiagnosticMessages(): any;
|
||||
|
@ -455,9 +454,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[];
|
||||
|
@ -469,28 +465,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;
|
||||
|
||||
|
@ -499,30 +497,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 {
|
||||
|
@ -543,14 +579,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 {
|
||||
|
@ -559,54 +595,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 {
|
||||
|
@ -694,7 +756,7 @@ module ts {
|
|||
filename: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: TypeScript.IScriptSnapshot,
|
||||
version: number,
|
||||
version: string,
|
||||
isOpen: boolean): SourceFile;
|
||||
|
||||
updateDocument(
|
||||
|
@ -702,7 +764,7 @@ module ts {
|
|||
filename: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: TypeScript.IScriptSnapshot,
|
||||
version: number,
|
||||
version: string,
|
||||
isOpen: boolean,
|
||||
textChangeRange: TypeScript.TextChangeRange
|
||||
): SourceFile;
|
||||
|
@ -820,7 +882,7 @@ module ts {
|
|||
// Information about a specific host file.
|
||||
interface HostFileInformation {
|
||||
filename: string;
|
||||
version: number;
|
||||
version: string;
|
||||
isOpen: boolean;
|
||||
sourceText?: TypeScript.IScriptSnapshot;
|
||||
}
|
||||
|
@ -929,7 +991,7 @@ module ts {
|
|||
return fileNames;
|
||||
}
|
||||
|
||||
public getVersion(filename: string): number {
|
||||
public getVersion(filename: string): string {
|
||||
return this.getEntry(filename).version;
|
||||
}
|
||||
|
||||
|
@ -945,14 +1007,14 @@ module ts {
|
|||
return file.sourceText;
|
||||
}
|
||||
|
||||
public getScriptTextChangeRangeSinceVersion(filename: string, lastKnownVersion: number): TypeScript.TextChangeRange {
|
||||
public getChangeRange(filename: string, lastKnownVersion: string, oldScriptSnapshot: TypeScript.IScriptSnapshot): TypeScript.TextChangeRange {
|
||||
var currentVersion = this.getVersion(filename);
|
||||
if (lastKnownVersion === currentVersion) {
|
||||
return TypeScript.TextChangeRange.unchanged; // "No changes"
|
||||
}
|
||||
|
||||
var scriptSnapshot = this.getScriptSnapshot(filename);
|
||||
return scriptSnapshot.getTextChangeRangeSinceVersion(lastKnownVersion);
|
||||
return scriptSnapshot.getChangeRange(oldScriptSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -961,11 +1023,10 @@ module ts {
|
|||
|
||||
// For our syntactic only features, we also keep a cache of the syntax tree for the
|
||||
// currently edited file.
|
||||
private currentfilename: string = "";
|
||||
private currentFileVersion: number = -1;
|
||||
private currentFilename: string = "";
|
||||
private currentFileVersion: string = null;
|
||||
private currentSourceFile: SourceFile = null;
|
||||
private currentFileSyntaxTree: TypeScript.SyntaxTree = null;
|
||||
private currentFileScriptSnapshot: TypeScript.IScriptSnapshot = null;
|
||||
|
||||
constructor(private host: LanguageServiceHost) {
|
||||
this.hostCache = new HostCache(host);
|
||||
|
@ -980,7 +1041,7 @@ module ts {
|
|||
var syntaxTree: TypeScript.SyntaxTree = null;
|
||||
var sourceFile: SourceFile;
|
||||
|
||||
if (this.currentFileSyntaxTree === null || this.currentfilename !== filename) {
|
||||
if (this.currentFileSyntaxTree === null || this.currentFilename !== filename) {
|
||||
var scriptSnapshot = this.hostCache.getScriptSnapshot(filename);
|
||||
syntaxTree = this.createSyntaxTree(filename, scriptSnapshot);
|
||||
sourceFile = createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true);
|
||||
|
@ -989,9 +1050,10 @@ module ts {
|
|||
}
|
||||
else if (this.currentFileVersion !== version) {
|
||||
var scriptSnapshot = this.hostCache.getScriptSnapshot(filename);
|
||||
syntaxTree = this.updateSyntaxTree(filename, scriptSnapshot, this.currentFileSyntaxTree, this.currentFileVersion);
|
||||
syntaxTree = this.updateSyntaxTree(filename, scriptSnapshot,
|
||||
this.currentSourceFile.getScriptSnapshot(), this.currentFileSyntaxTree, this.currentFileVersion);
|
||||
|
||||
var editRange = this.hostCache.getScriptTextChangeRangeSinceVersion(filename, this.currentFileVersion);
|
||||
var editRange = this.hostCache.getChangeRange(filename, this.currentFileVersion, this.currentSourceFile.getScriptSnapshot());
|
||||
sourceFile = !editRange
|
||||
? createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true)
|
||||
: this.currentSourceFile.update(scriptSnapshot, version, /*isOpen*/ true, editRange);
|
||||
|
@ -1002,9 +1064,8 @@ module ts {
|
|||
if (syntaxTree !== null) {
|
||||
Debug.assert(sourceFile);
|
||||
// All done, ensure state is up to date
|
||||
this.currentFileScriptSnapshot = scriptSnapshot;
|
||||
this.currentFileVersion = version;
|
||||
this.currentfilename = filename;
|
||||
this.currentFilename = filename;
|
||||
this.currentFileSyntaxTree = syntaxTree;
|
||||
this.currentSourceFile = sourceFile;
|
||||
}
|
||||
|
@ -1039,7 +1100,7 @@ module ts {
|
|||
public getCurrentScriptSnapshot(filename: string): TypeScript.IScriptSnapshot {
|
||||
// update currentFileScriptSnapshot as a part of 'getCurrentFileSyntaxTree' call
|
||||
this.getCurrentFileSyntaxTree(filename);
|
||||
return this.currentFileScriptSnapshot;
|
||||
return this.getCurrentSourceFile(filename).getScriptSnapshot();
|
||||
}
|
||||
|
||||
private createSyntaxTree(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot): TypeScript.SyntaxTree {
|
||||
|
@ -1053,8 +1114,8 @@ module ts {
|
|||
return syntaxTree;
|
||||
}
|
||||
|
||||
private updateSyntaxTree(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, previousSyntaxTree: TypeScript.SyntaxTree, previousFileVersion: number): TypeScript.SyntaxTree {
|
||||
var editRange = this.hostCache.getScriptTextChangeRangeSinceVersion(filename, previousFileVersion);
|
||||
private updateSyntaxTree(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, previousScriptSnapshot: TypeScript.IScriptSnapshot, previousSyntaxTree: TypeScript.SyntaxTree, previousFileVersion: string): TypeScript.SyntaxTree {
|
||||
var editRange = this.hostCache.getChangeRange(filename, previousFileVersion, previousScriptSnapshot);
|
||||
|
||||
// Debug.assert(newLength >= 0);
|
||||
|
||||
|
@ -1066,7 +1127,7 @@ module ts {
|
|||
var nextSyntaxTree = TypeScript.IncrementalParser.parse(
|
||||
previousSyntaxTree, editRange, TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot));
|
||||
|
||||
this.ensureInvariants(filename, editRange, nextSyntaxTree, this.currentFileScriptSnapshot, scriptSnapshot);
|
||||
this.ensureInvariants(filename, editRange, nextSyntaxTree, previousScriptSnapshot, scriptSnapshot);
|
||||
|
||||
return nextSyntaxTree;
|
||||
}
|
||||
|
@ -1134,7 +1195,7 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
function createSourceFileFromScriptSnapshot(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, settings: CompilerOptions, version: number, isOpen: boolean) {
|
||||
function createSourceFileFromScriptSnapshot(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, settings: CompilerOptions, version: string, isOpen: boolean) {
|
||||
return SourceFileObject.createSourceFileObject(filename, scriptSnapshot, settings.target, version, isOpen);
|
||||
}
|
||||
|
||||
|
@ -1179,7 +1240,7 @@ module ts {
|
|||
filename: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: TypeScript.IScriptSnapshot,
|
||||
version: number,
|
||||
version: string,
|
||||
isOpen: boolean): SourceFile {
|
||||
|
||||
var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
|
||||
|
@ -1203,7 +1264,7 @@ module ts {
|
|||
filename: string,
|
||||
compilationSettings: CompilerOptions,
|
||||
scriptSnapshot: TypeScript.IScriptSnapshot,
|
||||
version: number,
|
||||
version: string,
|
||||
isOpen: boolean,
|
||||
textChangeRange: TypeScript.TextChangeRange
|
||||
): SourceFile {
|
||||
|
@ -1397,7 +1458,7 @@ module ts {
|
|||
// new text buffer).
|
||||
var textChangeRange: TypeScript.TextChangeRange = null;
|
||||
if (sourceFile.isOpen && isOpen) {
|
||||
textChangeRange = hostCache.getScriptTextChangeRangeSinceVersion(filename, sourceFile.version);
|
||||
textChangeRange = hostCache.getChangeRange(filename, sourceFile.version, sourceFile.getScriptSnapshot());
|
||||
}
|
||||
|
||||
sourceFile = documentRegistry.updateDocument(sourceFile, filename, compilationSettings, scriptSnapshot, version, isOpen, textChangeRange);
|
||||
|
@ -1885,25 +1946,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 = typeInfoResolver.getSymbolInfo(node);
|
||||
var type = symbol && typeInfoResolver.getTypeOfSymbol(symbol);
|
||||
if (type) {
|
||||
return {
|
||||
memberName: new TypeScript.MemberNameString(typeInfoResolver.typeToString(type)),
|
||||
docComment: "",
|
||||
fullSymbolName: typeInfoResolver.symbolToString(symbol, getContainerNode(node)),
|
||||
kind: getSymbolKind(symbol),
|
||||
minChar: node.pos,
|
||||
limChar: node.end
|
||||
};
|
||||
return new TypeInfo(
|
||||
new TypeScript.MemberNameString(typeInfoResolver.typeToString(type)),
|
||||
"", typeInfoResolver.symbolToString(symbol, getContainerNode(node)),
|
||||
getSymbolKind(symbol), TypeScript.TextSpan.fromBounds(node.pos, node.end));
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
@ -1958,15 +2015,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[]) {
|
||||
|
@ -2036,11 +2091,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;
|
||||
}
|
||||
|
@ -2085,7 +2139,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();
|
||||
|
||||
|
@ -2136,10 +2190,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) {
|
||||
|
@ -2150,15 +2203,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);
|
||||
|
@ -2205,41 +2256,202 @@ 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);
|
||||
|
||||
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 [];
|
||||
function escapeRegExp(str: string): string {
|
||||
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
// 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 => "(" + 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 sourceFile = getCurrentSourceFile(fileName);
|
||||
var syntaxTree = sourceFile.getSyntaxTree();
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
var text = syntaxTree.text;
|
||||
var fileContents = text.substr(0, text.length());
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
var result: TodoComment[] = [];
|
||||
|
||||
if (descriptors.length > 0) {
|
||||
var regExp = getTodoCommentsRegExp(descriptors);
|
||||
|
||||
var matchArray: RegExpExecArray;
|
||||
while (matchArray = regExp.exec(fileContents)) {
|
||||
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 = 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 (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var message = matchArray[2];
|
||||
result.push(new TodoComment(descriptor, message, matchPosition));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function isLetterOrDigit(char: number): boolean {
|
||||
return (char >= TypeScript.CharacterCodes.a && char <= TypeScript.CharacterCodes.z) ||
|
||||
(char >= TypeScript.CharacterCodes.A && char <= TypeScript.CharacterCodes.Z) ||
|
||||
(char >= TypeScript.CharacterCodes._0 && char <= TypeScript.CharacterCodes._9);
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -2247,7 +2459,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) => [],
|
||||
|
@ -2255,27 +2468,44 @@ module ts {
|
|||
getNameOrDottedNameSpan: getNameOrDottedNameSpan,
|
||||
getBreakpointStatementAtPosition: getBreakpointStatementAtPosition,
|
||||
getNavigateToItems: (searchValue) => [],
|
||||
getScriptLexicalStructure: getScriptLexicalStructure,
|
||||
getOutliningRegions: getOutliningRegions,
|
||||
getRenameInfo: (fileName, position): RenameInfo => RenameInfo.CreateError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_this_element.key)),
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
/// Classifier
|
||||
export function createClassifier(host: Logger): Classifier {
|
||||
var scanner: Scanner;
|
||||
var noRegexTable: boolean[];
|
||||
var noRegexTable: boolean[];
|
||||
|
||||
/// We do not have a full parser support to know when we should parse a regex or not
|
||||
/// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where
|
||||
/// we have a series of divide operator. this list allows us to be more accurate by ruling out
|
||||
/// locations where a regexp cannot exist.
|
||||
if (!noRegexTable) {
noRegexTable = [];
noRegexTable[SyntaxKind.Identifier] = true;
noRegexTable[SyntaxKind.StringLiteral] = true;
noRegexTable[SyntaxKind.NumericLiteral] = true;
noRegexTable[SyntaxKind.RegularExpressionLiteral] = true;
noRegexTable[SyntaxKind.ThisKeyword] = true;
noRegexTable[SyntaxKind.PlusPlusToken] = true;
noRegexTable[SyntaxKind.MinusMinusToken] = true;
noRegexTable[SyntaxKind.CloseParenToken] = true;
noRegexTable[SyntaxKind.CloseBracketToken] = true;
noRegexTable[SyntaxKind.CloseBraceToken] = true;
noRegexTable[SyntaxKind.TrueKeyword] = true;
noRegexTable[SyntaxKind.FalseKeyword] = true;
}
|
||||
if (!noRegexTable) {
|
||||
noRegexTable = [];
|
||||
noRegexTable[SyntaxKind.Identifier] = true;
|
||||
noRegexTable[SyntaxKind.StringLiteral] = true;
|
||||
noRegexTable[SyntaxKind.NumericLiteral] = true;
|
||||
noRegexTable[SyntaxKind.RegularExpressionLiteral] = true;
|
||||
noRegexTable[SyntaxKind.ThisKeyword] = true;
|
||||
noRegexTable[SyntaxKind.PlusPlusToken] = true;
|
||||
noRegexTable[SyntaxKind.MinusMinusToken] = true;
|
||||
noRegexTable[SyntaxKind.CloseParenToken] = true;
|
||||
noRegexTable[SyntaxKind.CloseBracketToken] = true;
|
||||
noRegexTable[SyntaxKind.CloseBraceToken] = true;
|
||||
noRegexTable[SyntaxKind.TrueKeyword] = true;
|
||||
noRegexTable[SyntaxKind.FalseKeyword] = true;
|
||||
}
|
||||
|
||||
function getClassificationsForLine(text: string, lexState: EndOfLineState): ClassificationResult {
|
||||
var offset = 0;
|
||||
var lastTokenOrCommentEnd = 0;
|
||||
|
|
|
@ -36,7 +36,7 @@ module ts {
|
|||
// { span: { start: number; length: number }; newLength: number }
|
||||
//
|
||||
// Or null value if there was no change.
|
||||
getTextChangeRangeSinceVersion(scriptVersion: number): string;
|
||||
getChangeRange(oldSnapshot: ScriptSnapshotShim): string;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -48,7 +48,7 @@ module ts {
|
|||
// Returns a JSON encoded value of the type:
|
||||
// string[]
|
||||
getScriptFileNames(): string;
|
||||
getScriptVersion(fileName: string): number;
|
||||
getScriptVersion(fileName: string): string;
|
||||
getScriptIsOpen(fileName: string): boolean;
|
||||
getScriptSnapshot(fileName: string): ScriptSnapshotShim;
|
||||
getLocalizedDiagnosticMessages(): string;
|
||||
|
@ -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: <recursive use of this type>[] } [] = [];
|
||||
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;
|
||||
|
@ -283,8 +290,9 @@ module ts {
|
|||
return this.lineStartPositions;
|
||||
}
|
||||
|
||||
public getTextChangeRangeSinceVersion(scriptVersion: number): TypeScript.TextChangeRange {
|
||||
var encoded = this.scriptSnapshotShim.getTextChangeRangeSinceVersion(scriptVersion);
|
||||
public getChangeRange(oldSnapshot: TypeScript.IScriptSnapshot): TypeScript.TextChangeRange {
|
||||
var oldSnapshotShim = <ScriptSnapshotShimAdapter>oldSnapshot;
|
||||
var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim);
|
||||
if (encoded == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -295,30 +303,10 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
class LanguageServiceShimHostAdapter implements LanguageServiceHost {
|
||||
export class LanguageServiceShimHostAdapter implements LanguageServiceHost {
|
||||
constructor(private shimHost: LanguageServiceShimHost) {
|
||||
}
|
||||
|
||||
public information(): boolean {
|
||||
return this.shimHost.information();
|
||||
}
|
||||
|
||||
public debug(): boolean {
|
||||
return this.shimHost.debug();
|
||||
}
|
||||
|
||||
public warning(): boolean {
|
||||
return this.shimHost.warning();
|
||||
}
|
||||
|
||||
public error(): boolean {
|
||||
return this.shimHost.error();
|
||||
}
|
||||
|
||||
public fatal(): boolean {
|
||||
return this.shimHost.fatal();
|
||||
}
|
||||
|
||||
public log(s: string): void {
|
||||
this.shimHost.log(s);
|
||||
}
|
||||
|
@ -349,7 +337,7 @@ module ts {
|
|||
return new ScriptSnapshotShimAdapter(this.shimHost.getScriptSnapshot(fileName));
|
||||
}
|
||||
|
||||
public getScriptVersion(fileName: string): number {
|
||||
public getScriptVersion(fileName: string): string {
|
||||
return this.shimHost.getScriptVersion(fileName);
|
||||
}
|
||||
|
||||
|
@ -455,7 +443,6 @@ module ts {
|
|||
this.forwardJSONCall(
|
||||
"refresh(" + throwOnError + ")",
|
||||
() => {
|
||||
this.languageService.refresh();
|
||||
return <any>null;
|
||||
});
|
||||
}
|
||||
|
@ -468,8 +455,6 @@ module ts {
|
|||
return <any>null;
|
||||
});
|
||||
}
|
||||
/// SQUIGGLES
|
||||
///
|
||||
|
||||
private static realizeDiagnostic(diagnostic: Diagnostic): { message: string; start: number; length: number; category: string; } {
|
||||
return {
|
||||
|
@ -494,7 +479,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);
|
||||
|
@ -503,7 +488,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);
|
||||
|
@ -524,7 +509,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;
|
||||
|
@ -536,7 +521,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;
|
||||
|
@ -547,7 +532,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;
|
||||
|
@ -555,32 +540,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;
|
||||
|
@ -590,11 +592,10 @@ 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);
|
||||
return { value: columnOffset };
|
||||
return this.languageService.getIndentationAtPosition(fileName, position, localOptions);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -604,7 +605,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);
|
||||
});
|
||||
|
@ -612,7 +613,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);
|
||||
});
|
||||
|
@ -621,7 +622,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);
|
||||
});
|
||||
|
@ -634,7 +635,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;
|
||||
|
@ -644,52 +645,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;
|
||||
});
|
||||
|
@ -699,91 +686,57 @@ 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 {
|
||||
public classifier: Classifier;
|
||||
|
||||
constructor(factory: ShimFactory, public host: Logger) {
|
||||
constructor(factory: ShimFactory, public logger: Logger) {
|
||||
super(factory);
|
||||
this.classifier = createClassifier(this.host);
|
||||
this.classifier = createClassifier(this.logger);
|
||||
}
|
||||
|
||||
/// COLORIZATION
|
||||
|
@ -801,12 +754,12 @@ module ts {
|
|||
}
|
||||
|
||||
class CoreServicesShimObject extends ShimBase implements CoreServicesShim {
|
||||
constructor(factory: ShimFactory, public host: Logger) {
|
||||
constructor(factory: ShimFactory, public logger: Logger) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
private forwardJSONCall(actionDescription: string, action: () => any): any {
|
||||
return forwardJSONCall(this.host, actionDescription, action);
|
||||
return forwardJSONCall(this.logger, actionDescription, action);
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -814,7 +767,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;
|
||||
|
@ -849,22 +802,22 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
public createClassifierShim(host: Logger): ClassifierShim {
|
||||
public createClassifierShim(logger: Logger): ClassifierShim {
|
||||
try {
|
||||
return new ClassifierShimObject(this, host);
|
||||
return new ClassifierShimObject(this, logger);
|
||||
}
|
||||
catch (err) {
|
||||
logInternalError(host, err);
|
||||
logInternalError(logger, err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
public createCoreServicesShim(host: Logger): CoreServicesShim {
|
||||
public createCoreServicesShim(logger: Logger): CoreServicesShim {
|
||||
try {
|
||||
return new CoreServicesShimObject(this, host);
|
||||
return new CoreServicesShimObject(this, logger);
|
||||
}
|
||||
catch (err) {
|
||||
logInternalError(host, err);
|
||||
logInternalError(logger, err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,13 +38,15 @@ module TypeScript.Scanner {
|
|||
// _packedFullStartAndInfo:
|
||||
//
|
||||
// 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000x <-- has leading trivia
|
||||
// 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 00x0 <-- has trailing trivia
|
||||
// 0000 0000 0000 0000 0000 0000 0000 0000 00xx xxxx xxxx xxxx xxxx xxxx xxxx xx00 <-- full start
|
||||
// 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 00x0 <-- has leading comment (implies has leading trivia)
|
||||
// 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0x00 <-- has trailing trivia
|
||||
// 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 x000 <-- has trailing comment (implies has trailing trivia)
|
||||
// 0000 0000 0000 0000 0000 0000 0000 0000 00xx xxxx xxxx xxxx xxxx xxxx xxxx 0000 <-- full start
|
||||
// ^ ^ ^
|
||||
// | | |
|
||||
// Bit 64 Bit 30 Bit 1
|
||||
//
|
||||
// This gives us 28 bits for the start of the token. At 256MB That's more than enough for
|
||||
// This gives us 26 bits for the start of the token. At 64MB That's more than enough for
|
||||
// any codebase.
|
||||
//
|
||||
// _packedFullWidthAndKind:
|
||||
|
@ -58,31 +60,31 @@ module TypeScript.Scanner {
|
|||
// This gives us 23bit for width (or 8MB of width which should be enough for any codebase).
|
||||
|
||||
enum ScannerConstants {
|
||||
LargeTokenFullStartShift = 2,
|
||||
LargeTokenFullStartShift = 4,
|
||||
LargeTokenFullWidthShift = 7,
|
||||
LargeTokenLeadingTriviaBitMask = 0x01, // 00000001
|
||||
LargeTokenLeadingCommentBitMask = 0x02, // 00000010
|
||||
LargeTokenTrailingTriviaBitMask = 0x04, // 00000100
|
||||
LargeTokenTrailingCommentBitMask = 0x08, // 00001000
|
||||
LargeTokenTriviaBitMask = 0x0F, // 00001111
|
||||
|
||||
FixedWidthTokenFullStartShift = 7,
|
||||
FixedWidthTokenMaxFullStart = 0x7FFFFF, // 23 ones.
|
||||
|
||||
SmallTokenFullWidthShift = 7,
|
||||
SmallTokenFullStartShift = 12,
|
||||
SmallTokenMaxFullStart = 0x3FFFF, // 18 ones.
|
||||
SmallTokenMaxFullWidth = 0x1F, // 5 ones
|
||||
SmallTokenFullWidthMask = 0x1F, // 00011111
|
||||
|
||||
KindMask = 0x7F, // 01111111
|
||||
IsVariableWidthMask = 0x80, // 10000000
|
||||
|
||||
LargeTokenLeadingTriviaBitMask = 0x01, // 00000001
|
||||
LargeTokenTrailingTriviaBitMask = 0x02, // 00000010
|
||||
|
||||
SmallTokenFullWidthMask = 0x1F, // 00011111
|
||||
|
||||
FixedWidthTokenMaxFullStart = 0x7FFFFF, // 23 ones.
|
||||
SmallTokenMaxFullStart = 0x3FFFF, // 18 ones.
|
||||
SmallTokenMaxFullWidth = 0x1F, // 5 ones
|
||||
}
|
||||
|
||||
// Make sure our math works for packing/unpacking large fullStarts.
|
||||
Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(1 << 28, 1, 1)) === (1 << 28));
|
||||
Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(3 << 27, 0, 1)) === (3 << 27));
|
||||
Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(10 << 25, 1, 0)) === (10 << 25));
|
||||
Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(1 << 26, 3)) === (1 << 26));
|
||||
Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(3 << 25, 1)) === (3 << 25));
|
||||
Debug.assert(largeTokenUnpackFullStart(largeTokenPackFullStartAndInfo(10 << 23, 2)) === (10 << 23));
|
||||
|
||||
function fixedWidthTokenPackData(fullStart: number, kind: SyntaxKind) {
|
||||
return (fullStart << ScannerConstants.FixedWidthTokenFullStartShift) | kind;
|
||||
|
@ -94,8 +96,8 @@ module TypeScript.Scanner {
|
|||
|
||||
function smallTokenPackData(fullStart: number, fullWidth: number, kind: SyntaxKind) {
|
||||
return (fullStart << ScannerConstants.SmallTokenFullStartShift) |
|
||||
(fullWidth << ScannerConstants.SmallTokenFullWidthShift) |
|
||||
kind;
|
||||
(fullWidth << ScannerConstants.SmallTokenFullWidthShift) |
|
||||
kind;
|
||||
}
|
||||
|
||||
function smallTokenUnpackFullWidth(packedData: number): SyntaxKind {
|
||||
|
@ -106,8 +108,8 @@ module TypeScript.Scanner {
|
|||
return packedData >> ScannerConstants.SmallTokenFullStartShift;
|
||||
}
|
||||
|
||||
function largeTokenPackFullStartAndInfo(fullStart: number, hasLeadingTriviaInfo: number, hasTrailingTriviaInfo: number): number {
|
||||
return (fullStart << ScannerConstants.LargeTokenFullStartShift) | hasLeadingTriviaInfo | hasTrailingTriviaInfo;
|
||||
function largeTokenPackFullStartAndInfo(fullStart: number, triviaInfo: number): number {
|
||||
return (fullStart << ScannerConstants.LargeTokenFullStartShift) | triviaInfo;
|
||||
}
|
||||
|
||||
function largeTokenUnpackFullWidth(packedFullWidthAndKind: number) {
|
||||
|
@ -118,12 +120,24 @@ module TypeScript.Scanner {
|
|||
return packedFullStartAndInfo >> ScannerConstants.LargeTokenFullStartShift;
|
||||
}
|
||||
|
||||
function largeTokenUnpackHasLeadingTriviaInfo(packed: number): number {
|
||||
return packed & ScannerConstants.LargeTokenLeadingTriviaBitMask;
|
||||
function largeTokenUnpackHasLeadingTrivia(packed: number): boolean {
|
||||
return (packed & ScannerConstants.LargeTokenLeadingTriviaBitMask) !== 0;
|
||||
}
|
||||
|
||||
function largeTokenUnpackHasTrailingTriviaInfo(packed: number): number {
|
||||
return packed & ScannerConstants.LargeTokenTrailingTriviaBitMask;
|
||||
function largeTokenUnpackHasTrailingTrivia(packed: number): boolean {
|
||||
return (packed & ScannerConstants.LargeTokenTrailingTriviaBitMask) !== 0;
|
||||
}
|
||||
|
||||
function largeTokenUnpackHasLeadingComment(packed: number): boolean {
|
||||
return (packed & ScannerConstants.LargeTokenLeadingCommentBitMask) !== 0;
|
||||
}
|
||||
|
||||
function largeTokenUnpackHasTrailingComment(packed: number): boolean {
|
||||
return (packed & ScannerConstants.LargeTokenTrailingCommentBitMask) !== 0;
|
||||
}
|
||||
|
||||
function largeTokenUnpackTriviaInfo(packed: number): number {
|
||||
return packed & ScannerConstants.LargeTokenTriviaBitMask;
|
||||
}
|
||||
|
||||
var isKeywordStartCharacter: number[] = ArrayUtilities.createArray<number>(CharacterCodes.maxAsciiCharacter, 0);
|
||||
|
@ -174,7 +188,7 @@ module TypeScript.Scanner {
|
|||
|
||||
var triviaScanner = createScannerInternal(ts.ScriptTarget.ES5, SimpleText.fromString(""), () => { });
|
||||
|
||||
interface IScannerToken extends ISyntaxToken {
|
||||
interface IScannerToken extends ISyntaxToken {
|
||||
}
|
||||
|
||||
function fillSizeInfo(token: IScannerToken, text: ISimpleText): void {
|
||||
|
@ -256,6 +270,8 @@ module TypeScript.Scanner {
|
|||
public fullStart(): number { return fixedWidthTokenUnpackFullStart(this._packedData); }
|
||||
public hasLeadingTrivia(): boolean { return false; }
|
||||
public hasTrailingTrivia(): boolean { return false; }
|
||||
public hasLeadingComment(): boolean { return false; }
|
||||
public hasTrailingComment(): boolean { return false; }
|
||||
public clone(): ISyntaxToken { return new FixedWidthTokenWithNoTrivia(this._packedData); }
|
||||
}
|
||||
|
||||
|
@ -271,19 +287,18 @@ module TypeScript.Scanner {
|
|||
|
||||
public setFullStart(fullStart: number): void {
|
||||
this._packedFullStartAndInfo = largeTokenPackFullStartAndInfo(fullStart,
|
||||
largeTokenUnpackHasLeadingTriviaInfo(this._packedFullStartAndInfo),
|
||||
largeTokenUnpackHasTrailingTriviaInfo(this._packedFullStartAndInfo));
|
||||
largeTokenUnpackTriviaInfo(this._packedFullStartAndInfo));
|
||||
}
|
||||
|
||||
private syntaxTreeText(text: ISimpleText) {
|
||||
private syntaxTreeText(text: ISimpleText) {
|
||||
var result = text || syntaxTree(this).text;
|
||||
Debug.assert(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public isIncrementallyUnusable(): boolean { return tokenIsIncrementallyUnusable(this); }
|
||||
public isKeywordConvertedToIdentifier(): boolean { return false; }
|
||||
public hasSkippedToken(): boolean { return false; }
|
||||
public isIncrementallyUnusable(): boolean { return tokenIsIncrementallyUnusable(this); }
|
||||
public isKeywordConvertedToIdentifier(): boolean { return false; }
|
||||
public hasSkippedToken(): boolean { return false; }
|
||||
|
||||
public fullText(text?: ISimpleText): string {
|
||||
return fullText(this, this.syntaxTreeText(text));
|
||||
|
@ -294,8 +309,8 @@ module TypeScript.Scanner {
|
|||
return cachedText !== undefined ? cachedText : SyntaxFacts.getText(this.kind());
|
||||
}
|
||||
|
||||
public leadingTrivia(text?: ISimpleText): ISyntaxTriviaList { return leadingTrivia(this, this.syntaxTreeText(text)); }
|
||||
public trailingTrivia(text?: ISimpleText): ISyntaxTriviaList { return trailingTrivia(this, this.syntaxTreeText(text)); }
|
||||
public leadingTrivia(text?: ISimpleText): ISyntaxTriviaList { return leadingTrivia(this, this.syntaxTreeText(text)); }
|
||||
public trailingTrivia(text?: ISimpleText): ISyntaxTriviaList { return trailingTrivia(this, this.syntaxTreeText(text)); }
|
||||
|
||||
public leadingTriviaWidth(text?: ISimpleText): number {
|
||||
return leadingTriviaWidth(this, this.syntaxTreeText(text));
|
||||
|
@ -308,8 +323,10 @@ module TypeScript.Scanner {
|
|||
public kind(): SyntaxKind { return this._packedFullWidthAndKind & ScannerConstants.KindMask; }
|
||||
public fullWidth(): number { return largeTokenUnpackFullWidth(this._packedFullWidthAndKind); }
|
||||
public fullStart(): number { return largeTokenUnpackFullStart(this._packedFullStartAndInfo); }
|
||||
public hasLeadingTrivia(): boolean { return largeTokenUnpackHasLeadingTriviaInfo(this._packedFullStartAndInfo) !== 0; }
|
||||
public hasTrailingTrivia(): boolean { return largeTokenUnpackHasTrailingTriviaInfo(this._packedFullStartAndInfo) !== 0; }
|
||||
public hasLeadingTrivia(): boolean { return largeTokenUnpackHasLeadingTrivia(this._packedFullStartAndInfo); }
|
||||
public hasTrailingTrivia(): boolean { return largeTokenUnpackHasTrailingTrivia(this._packedFullStartAndInfo); }
|
||||
public hasLeadingComment(): boolean { return largeTokenUnpackHasLeadingComment(this._packedFullStartAndInfo); }
|
||||
public hasTrailingComment(): boolean { return largeTokenUnpackHasTrailingComment(this._packedFullStartAndInfo); }
|
||||
public clone(): ISyntaxToken { return new LargeScannerToken(this._packedFullStartAndInfo, this._packedFullWidthAndKind, this.cachedText); }
|
||||
}
|
||||
|
||||
|
@ -351,8 +368,8 @@ module TypeScript.Scanner {
|
|||
}
|
||||
|
||||
function reset(_text: ISimpleText, _start: number, _end: number) {
|
||||
Debug.assert(_start <= _text.length());
|
||||
Debug.assert(_end <= _text.length());
|
||||
Debug.assert(_start <= _text.length(), "Token's start was not within the bounds of text: " + _start + " - [0, " + _text.length() + ")");
|
||||
Debug.assert(_end <= _text.length(), "Token's end was not within the bounds of text: " + _end + " - [0, " + _text.length() + ")");
|
||||
|
||||
if (!str || text !== _text) {
|
||||
text = _text;
|
||||
|
@ -392,7 +409,7 @@ module TypeScript.Scanner {
|
|||
else {
|
||||
// inline the packing logic for perf.
|
||||
var packedFullStartAndTriviaInfo = (fullStart << ScannerConstants.LargeTokenFullStartShift) |
|
||||
leadingTriviaInfo | (trailingTriviaInfo << 1);
|
||||
leadingTriviaInfo | (trailingTriviaInfo << 2);
|
||||
|
||||
var packedFullWidthAndKind = (fullWidth << ScannerConstants.LargeTokenFullWidthShift) | kind;
|
||||
var cachedText = isFixedWidth ? undefined : text.substr(start, end - start);
|
||||
|
@ -505,7 +522,8 @@ module TypeScript.Scanner {
|
|||
case CharacterCodes.verticalTab:
|
||||
case CharacterCodes.formFeed:
|
||||
index++;
|
||||
result = 1;
|
||||
// we have trivia
|
||||
result |= 1;
|
||||
continue;
|
||||
|
||||
case CharacterCodes.carriageReturn:
|
||||
|
@ -516,27 +534,31 @@ module TypeScript.Scanner {
|
|||
case CharacterCodes.lineFeed:
|
||||
index++;
|
||||
|
||||
// we have trivia
|
||||
result |= 1;
|
||||
|
||||
// If we're consuming leading trivia, then we will continue consuming more
|
||||
// trivia (including newlines) up to the first token we see. If we're
|
||||
// consuming trailing trivia, then we break after the first newline we see.
|
||||
if (isTrailing) {
|
||||
return 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
result = 1;
|
||||
continue;
|
||||
|
||||
case CharacterCodes.slash:
|
||||
if ((index + 1) < _end) {
|
||||
var ch2 = str.charCodeAt(index + 1);
|
||||
if (ch2 === CharacterCodes.slash) {
|
||||
result = 1;
|
||||
// we have a comment, and we have trivia
|
||||
result |= 3;
|
||||
skipSingleLineCommentTrivia();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch2 === CharacterCodes.asterisk) {
|
||||
result = 1;
|
||||
// we have a comment, and we have trivia
|
||||
result |= 3;
|
||||
skipMultiLineCommentTrivia();
|
||||
continue;
|
||||
}
|
||||
|
@ -547,7 +569,7 @@ module TypeScript.Scanner {
|
|||
|
||||
default:
|
||||
if (ch > CharacterCodes.maxAsciiCharacter && slowScanTriviaInfo(ch)) {
|
||||
result = 1;
|
||||
result |= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1427,7 +1449,7 @@ module TypeScript.Scanner {
|
|||
var fullEnd = fullStart + token.fullWidth();
|
||||
reset(text, fullStart, fullEnd);
|
||||
|
||||
var leadingTriviaInfo = scanTriviaInfo(/*isTrailing: */ false);
|
||||
scanTriviaInfo(/*isTrailing: */ false);
|
||||
|
||||
var start = index;
|
||||
scanSyntaxKind(isContextualToken(token));
|
||||
|
@ -1616,6 +1638,8 @@ module TypeScript.Scanner {
|
|||
}
|
||||
|
||||
function resetToPosition(absolutePosition: number): void {
|
||||
Debug.assert(absolutePosition <= text.length(), "Trying to set the position outside the bounds of the text!");
|
||||
|
||||
_absolutePosition = absolutePosition;
|
||||
|
||||
// First, remove any diagnostics that came after this position.
|
||||
|
|
|
@ -17,6 +17,8 @@ module TypeScript {
|
|||
|
||||
hasLeadingTrivia(): boolean;
|
||||
hasTrailingTrivia(): boolean;
|
||||
hasLeadingComment(): boolean;
|
||||
hasTrailingComment(): boolean;
|
||||
|
||||
hasSkippedToken(): boolean;
|
||||
|
||||
|
@ -264,7 +266,7 @@ module TypeScript.Syntax {
|
|||
export function realizeToken(token: ISyntaxToken, text: ISimpleText): ISyntaxToken {
|
||||
return new RealizedToken(token.fullStart(), token.kind(), token.isKeywordConvertedToIdentifier(), token.leadingTrivia(text), token.text(), token.trailingTrivia(text));
|
||||
}
|
||||
|
||||
|
||||
export function convertKeywordToIdentifier(token: ISyntaxToken): ISyntaxToken {
|
||||
return new ConvertedKeywordToken(token);
|
||||
}
|
||||
|
@ -381,11 +383,14 @@ module TypeScript.Syntax {
|
|||
public fullText(): string { return ""; }
|
||||
|
||||
public hasLeadingTrivia() { return false; }
|
||||
public leadingTriviaWidth() { return 0; }
|
||||
public hasTrailingTrivia() { return false; }
|
||||
public hasLeadingComment() { return false; }
|
||||
public hasTrailingComment() { return false; }
|
||||
public hasSkippedToken() { return false; }
|
||||
|
||||
public leadingTriviaWidth() { return 0; }
|
||||
public trailingTriviaWidth() { return 0; }
|
||||
|
||||
public leadingTrivia(): ISyntaxTriviaList { return Syntax.emptyTriviaList; }
|
||||
public trailingTrivia(): ISyntaxTriviaList { return Syntax.emptyTriviaList; }
|
||||
}
|
||||
|
@ -401,11 +406,11 @@ module TypeScript.Syntax {
|
|||
public _primaryExpressionBrand: any; public _memberExpressionBrand: any; public _leftHandSideExpressionBrand: any; public _postfixExpressionBrand: any; public _unaryExpressionBrand: any; public _expressionBrand: any; public _typeBrand: any;
|
||||
|
||||
constructor(fullStart: number,
|
||||
kind: SyntaxKind,
|
||||
isKeywordConvertedToIdentifier: boolean,
|
||||
leadingTrivia: ISyntaxTriviaList,
|
||||
text: string,
|
||||
trailingTrivia: ISyntaxTriviaList) {
|
||||
kind: SyntaxKind,
|
||||
isKeywordConvertedToIdentifier: boolean,
|
||||
leadingTrivia: ISyntaxTriviaList,
|
||||
text: string,
|
||||
trailingTrivia: ISyntaxTriviaList) {
|
||||
this._fullStart = fullStart;
|
||||
this._kind = kind;
|
||||
this._isKeywordConvertedToIdentifier = isKeywordConvertedToIdentifier;
|
||||
|
@ -438,8 +443,8 @@ module TypeScript.Syntax {
|
|||
// Realized tokens are created from the parser. They are *never* incrementally reusable.
|
||||
public isIncrementallyUnusable() { return true; }
|
||||
|
||||
public isKeywordConvertedToIdentifier() {
|
||||
return this._isKeywordConvertedToIdentifier;
|
||||
public isKeywordConvertedToIdentifier() {
|
||||
return this._isKeywordConvertedToIdentifier;
|
||||
}
|
||||
|
||||
public fullStart(): number { return this._fullStart; }
|
||||
|
@ -450,6 +455,8 @@ module TypeScript.Syntax {
|
|||
|
||||
public hasLeadingTrivia(): boolean { return this._leadingTrivia.count() > 0; }
|
||||
public hasTrailingTrivia(): boolean { return this._trailingTrivia.count() > 0; }
|
||||
public hasLeadingComment(): boolean { return this._leadingTrivia.hasComment(); }
|
||||
public hasTrailingComment(): boolean { return this._trailingTrivia.hasComment(); }
|
||||
|
||||
public leadingTriviaWidth(): number { return this._leadingTrivia.fullWidth(); }
|
||||
public trailingTriviaWidth(): number { return this._trailingTrivia.fullWidth(); }
|
||||
|
@ -504,6 +511,14 @@ module TypeScript.Syntax {
|
|||
return this.underlyingToken.hasTrailingTrivia();
|
||||
}
|
||||
|
||||
public hasLeadingComment(): boolean {
|
||||
return this.underlyingToken.hasLeadingComment();
|
||||
}
|
||||
|
||||
public hasTrailingComment(): boolean {
|
||||
return this.underlyingToken.hasTrailingComment();
|
||||
}
|
||||
|
||||
public hasSkippedToken(): boolean {
|
||||
return this.underlyingToken.hasSkippedToken();
|
||||
}
|
||||
|
|
|
@ -16,10 +16,12 @@ module TypeScript {
|
|||
// always determine this (albeit in a more expensive manner).
|
||||
getLineStartPositions(): number[];
|
||||
|
||||
// Returns a text change range representing what text has changed since the specified version.
|
||||
// If the change cannot be determined (say, because a file was opened/closed), then 'null'
|
||||
// should be returned.
|
||||
getTextChangeRangeSinceVersion(scriptVersion: number): TextChangeRange;
|
||||
// Gets the TextChangeRange that describe how the text changed between this text and
|
||||
// an older version. This informatoin is used by the incremental parser to determine
|
||||
// what sections of the script need to be reparsed. 'null' can be returned if the
|
||||
// change range cannot be determined. However, in that case, incremental parsing will
|
||||
// not happen and the entire document will be reparsed.
|
||||
getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange;
|
||||
}
|
||||
|
||||
export module ScriptSnapshot {
|
||||
|
@ -45,7 +47,7 @@ module TypeScript {
|
|||
return this._lineStartPositions;
|
||||
}
|
||||
|
||||
public getTextChangeRangeSinceVersion(scriptVersion: number): TypeScript.TextChangeRange {
|
||||
public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange {
|
||||
throw Errors.notYetImplemented();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@ module TypeScript {
|
|||
this._length = length;
|
||||
}
|
||||
|
||||
public toJSON(key: any): any {
|
||||
return { start: this._start, length: this._length };
|
||||
}
|
||||
|
||||
public start(): number {
|
||||
return this._start;
|
||||
}
|
||||
|
|
3
tests/cases/fourslash/todoComments1.ts
Normal file
3
tests/cases/fourslash/todoComments1.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
//// // [|TODO|]
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO"]);
|
6
tests/cases/fourslash/todoComments10.ts
Normal file
6
tests/cases/fourslash/todoComments10.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
//// /*
|
||||
//// [|todo 1|]
|
||||
//// [|hack 2|]
|
||||
//// */
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO", "HACK"]);
|
6
tests/cases/fourslash/todoComments11.ts
Normal file
6
tests/cases/fourslash/todoComments11.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
//// /*
|
||||
//// [|TODO(jason) 1|]
|
||||
//// [|HACK 2|]
|
||||
//// */
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO(jason)", "HACK"]);
|
6
tests/cases/fourslash/todoComments12.ts
Normal file
6
tests/cases/fourslash/todoComments12.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
//// /*
|
||||
//// [|TODO(jason) 1|]
|
||||
//// [|HACK 2|]
|
||||
//// */
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["HACK", "TODO(jason)"]);
|
4
tests/cases/fourslash/todoComments13.ts
Normal file
4
tests/cases/fourslash/todoComments13.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
//// TODO
|
||||
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO"]);
|
3
tests/cases/fourslash/todoComments14.ts
Normal file
3
tests/cases/fourslash/todoComments14.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
//// BAR // [|TODO|]
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO"]);
|
3
tests/cases/fourslash/todoComments15.ts
Normal file
3
tests/cases/fourslash/todoComments15.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
//// "// HACK 1";
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO(jason)", "HACK"]);
|
3
tests/cases/fourslash/todoComments16.ts
Normal file
3
tests/cases/fourslash/todoComments16.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
//// //// [|HACK 1|]
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO(jason)", "HACK"]);
|
3
tests/cases/fourslash/todoComments17.ts
Normal file
3
tests/cases/fourslash/todoComments17.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
//// /**** [|HACK 1 |]*/ a
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO(jason)", "HACK"]);
|
3
tests/cases/fourslash/todoComments2.ts
Normal file
3
tests/cases/fourslash/todoComments2.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
//// // not TODO
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO"]);
|
3
tests/cases/fourslash/todoComments3.ts
Normal file
3
tests/cases/fourslash/todoComments3.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
//// // [|TODO with stuff|]
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO"]);
|
3
tests/cases/fourslash/todoComments4.ts
Normal file
3
tests/cases/fourslash/todoComments4.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
//// // TODOnomatch
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO"]);
|
6
tests/cases/fourslash/todoComments5.ts
Normal file
6
tests/cases/fourslash/todoComments5.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
//// /*
|
||||
//// [|TODO 1|]
|
||||
//// [|TODO 2|]
|
||||
//// */
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO"]);
|
6
tests/cases/fourslash/todoComments6.ts
Normal file
6
tests/cases/fourslash/todoComments6.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
//// /*
|
||||
//// * [|TODO 1|]
|
||||
//// * [|TODO 2|]
|
||||
//// */
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO"]);
|
6
tests/cases/fourslash/todoComments7.ts
Normal file
6
tests/cases/fourslash/todoComments7.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
//// /*
|
||||
//// [|TODO 1|]
|
||||
//// [|HACK 2|]
|
||||
//// */
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO", "HACK"]);
|
6
tests/cases/fourslash/todoComments8.ts
Normal file
6
tests/cases/fourslash/todoComments8.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
//// /*
|
||||
//// [|HACK 1|]
|
||||
//// [|TODO 2|]
|
||||
//// */
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO", "HACK"]);
|
6
tests/cases/fourslash/todoComments9.ts
Normal file
6
tests/cases/fourslash/todoComments9.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
//// /*
|
||||
//// [|TODO HACK|]
|
||||
//// [|HACK TODO|]
|
||||
//// */
|
||||
debugger;
|
||||
verify.todoCommentsInCurrentFile(["TODO", "HACK"]);
|
Loading…
Reference in a new issue