Merge branch 'master' into getReferences

Conflicts:
	src/services/services.ts
This commit is contained in:
Daniel Rosenwasser
2014-08-25 16:51:35 -07:00
105 changed files with 1841 additions and 1287 deletions
+1
View File
@@ -71,6 +71,7 @@ var harnessSources = [
"fourslashRunner.ts",
"projectsRunner.ts",
"unittestrunner.ts",
"loggedIO.ts",
"rwcRunner.ts",
"runner.ts"
].map(function (f) {
+1 -1
View File
@@ -1472,7 +1472,7 @@ module ts {
function getTypeOfFuncClassEnumModule(symbol: Symbol): Type {
var links = getSymbolLinks(symbol);
if (!links.type) {
var type = links.type = createObjectType(TypeFlags.Anonymous, symbol);
links.type = createObjectType(TypeFlags.Anonymous, symbol);
}
return links.type;
}
+2 -5
View File
@@ -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;
}
@@ -567,7 +564,7 @@ module ts {
var currentAssertionLevel = AssertionLevel.None;
export function shouldAssert(level: AssertionLevel): boolean {
return this.currentAssertionLevel >= level;
return currentAssertionLevel >= level;
}
export function assert(expression: any, message?: string, verboseDebugInfo?: () => string): void {
@@ -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." },
};
}
+4 -1
View File
@@ -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
}
}
+48 -13
View File
@@ -330,6 +330,8 @@ module ts {
/** Emit Trailing comments of the node */
var emitTrailingComments = compilerOptions.removeComments ? (node: Node) => { } : emitTrailingDeclarationComments;
var emitLeadingCommentsOfPosition = compilerOptions.removeComments ? (pos: number) => { } : emitLeadingCommentsOfLocalPosition;
var detachedCommentsInfo: { nodePos: number; detachedCommentEndPos: number }[];
/** Emit detached comments of the node */
var emitDetachedComments = compilerOptions.removeComments ? (node: TextRange) => { } : emitDetachedCommentsAtPosition;
@@ -1390,12 +1392,14 @@ module ts {
write(";");
emitTrailingComments(node.body);
}
decreaseIndent();
writeLine();
if (node.body.kind === SyntaxKind.FunctionBlock) {
emitLeadingCommentsOfPosition((<Block>node.body).statements.end);
decreaseIndent();
emitToken(SyntaxKind.CloseBraceToken, (<Block>node.body).statements.end);
}
else {
decreaseIndent();
emitStart(node.body);
write("}");
emitEnd(node.body);
@@ -1648,8 +1652,11 @@ module ts {
if (superCall) statements = statements.slice(1);
emitLines(statements);
}
decreaseIndent();
writeLine();
if (ctor) {
emitLeadingCommentsOfPosition((<Block>ctor.body).statements.end);
}
decreaseIndent();
emitToken(SyntaxKind.CloseBraceToken, ctor ? (<Block>ctor.body).statements.end : node.members.end);
scopeEmitEnd();
emitEnd(<Node>ctor || node);
@@ -1925,6 +1932,8 @@ module ts {
function emitSourceFile(node: SourceFile) {
currentSourceFile = node;
// Start new file on new line
writeLine();
emitDetachedComments(node);
// emit prologue directives prior to __extends
var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false);
@@ -2075,23 +2084,34 @@ module ts {
}
}
function hasDetachedComments(pos: number) {
return detachedCommentsInfo !== undefined && detachedCommentsInfo[detachedCommentsInfo.length - 1].nodePos === pos;
}
function getLeadingCommentsWithoutDetachedComments() {
// get the leading comments from detachedPos
var leadingComments = getLeadingComments(currentSourceFile.text, detachedCommentsInfo[detachedCommentsInfo.length - 1].detachedCommentEndPos);
if (detachedCommentsInfo.length - 1) {
detachedCommentsInfo.pop();
}
else {
detachedCommentsInfo = undefined;
}
return leadingComments;
}
function emitLeadingDeclarationComments(node: Node) {
// Emit the leading comments only if the parent's pos doesnt match because parent should take care of emitting these comments
if (node.parent.kind === SyntaxKind.SourceFile || node.pos !== node.parent.pos) {
var leadingComments: Comment[];
if (detachedCommentsInfo === undefined || detachedCommentsInfo[detachedCommentsInfo.length - 1].nodePos !== node.pos) {
// get the leading comments from the node
leadingComments = getLeadingCommentsOfNode(node, currentSourceFile);
if (hasDetachedComments(node.pos)) {
// get comments without detached comments
leadingComments = getLeadingCommentsWithoutDetachedComments();
}
else {
// get the leading comments from detachedPos
leadingComments = getLeadingComments(currentSourceFile.text, detachedCommentsInfo[detachedCommentsInfo.length - 1].detachedCommentEndPos);
if (detachedCommentsInfo.length - 1) {
detachedCommentsInfo.pop();
}
else {
detachedCommentsInfo = undefined;
}
// get the leading comments from the node
leadingComments = getLeadingCommentsOfNode(node, currentSourceFile);
}
emitNewLineBeforeLeadingComments(node, leadingComments, writer);
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
@@ -2108,6 +2128,21 @@ module ts {
}
}
function emitLeadingCommentsOfLocalPosition(pos: number) {
var leadingComments: Comment[];
if (hasDetachedComments(pos)) {
// get comments without detached comments
leadingComments = getLeadingCommentsWithoutDetachedComments();
}
else {
// get the leading comments from the node
leadingComments = getLeadingComments(currentSourceFile.text, pos);
}
emitNewLineBeforeLeadingComments({ pos: pos, end: pos }, leadingComments, writer);
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(leadingComments, /*trailingSeparator*/ true, writer, writeComment);
}
function emitDetachedCommentsAtPosition(node: TextRange) {
var leadingComments = getLeadingComments(currentSourceFile.text, node.pos);
if (leadingComments) {
+2 -4
View File
@@ -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;
@@ -483,7 +483,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;
@@ -2455,8 +2455,6 @@ module ts {
function parseBreakOrContinueStatement(kind: SyntaxKind): BreakOrContinueStatement {
var node = <BreakOrContinueStatement>createNode(kind);
var errorCountBeforeStatement = file.syntacticErrors.length;
var keywordStart = scanner.getTokenPos();
var keywordLength = scanner.getTextPos() - keywordStart;
parseExpected(kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword);
if (!canParseSemicolon()) node.label = parseIdentifier();
parseSemicolon();
+10 -5
View File
@@ -86,13 +86,18 @@ module ts {
}
function reportDiagnostic(diagnostic: Diagnostic) {
var output = "";
if (diagnostic.file) {
var loc = diagnostic.file.getLineAndCharacterFromPosition(diagnostic.start);
sys.write(diagnostic.file.filename + "(" + loc.line + "," + loc.character + "): " + diagnostic.messageText + sys.newLine);
}
else {
sys.write(diagnostic.messageText + sys.newLine);
output += diagnostic.file.filename + "(" + loc.line + "," + loc.character + "): ";
}
var category = DiagnosticCategory[diagnostic.category].toLowerCase();
output += category + " TS" + diagnostic.code + ": " + diagnostic.messageText + sys.newLine;
sys.write(output);
}
function reportDiagnostics(diagnostics: Diagnostic[]) {
@@ -142,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) {
+1 -1
View File
@@ -535,7 +535,7 @@ module ts {
identifierCount: number;
symbolCount: number;
isOpen: boolean;
version: number;
version: string;
languageVersion: ScriptTarget;
identifiers: Map<string>;
}
+29 -8
View File
@@ -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) {
+100 -105
View File
@@ -754,22 +754,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);
}
@@ -778,16 +778,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);
}
@@ -800,13 +798,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);
}
@@ -814,15 +812,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");
@@ -834,45 +832,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) {
@@ -881,7 +866,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;
}
@@ -912,7 +897,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));
}
@@ -1105,7 +1090,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);
@@ -1145,7 +1130,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);
}
@@ -1209,18 +1194,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);
@@ -1240,7 +1225,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();
}
@@ -1297,7 +1282,7 @@ module FourSlash {
var definition = definitions[definitionIndex];
this.openFile(definition.fileName);
this.currentCaretPosition = definition.minChar;
this.currentCaretPosition = definition.textSpan.start();
}
public verifyDefinitionLocationExists(negative: boolean) {
@@ -1403,7 +1388,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' +
@@ -1415,7 +1400,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;
}
@@ -1444,7 +1429,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);
@@ -1459,6 +1444,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';
@@ -1618,70 +1622,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) {
@@ -1697,14 +1692,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);
}
}
@@ -1723,7 +1718,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 + '.');
}
@@ -1929,12 +1924,12 @@ 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[fourslashFilename] = fourslashSourceFile;
files[fileName] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5, /*version*/ 0, /*isOpen*/ false);
files[Harness.Compiler.defaultLibFileName] = Harness.Compiler.defaultLibSourceFile;
files[ts.getCanonicalFileName(fourslashFilename)] = fourslashSourceFile;
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);
var program = ts.createProgram([fourslashFilename, fileName], { out: "fourslashTestOutput.js" }, host);
+38 -13
View File
@@ -532,15 +532,15 @@ 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 {
getCurrentDirectory: sys.getCurrentDirectory,
getCancellationToken: (): any => undefined,
getSourceFile: (fn, languageVersion) => {
if (fn in filemap) {
return filemap[fn];
if (Object.prototype.hasOwnProperty.call(filemap, ts.getCanonicalFileName(fn))) {
return filemap[ts.getCanonicalFileName(fn)];
} else {
var lib = defaultLibFileName;
if (fn === defaultLibFileName) {
@@ -563,7 +563,7 @@ module Harness {
private compileOptions: ts.CompilerOptions;
private settings: Harness.TestCaseParser.CompilerSetting[] = [];
private lastErrors: MinimalDiagnostic[];
private lastErrors: HarnessDiagnostic[];
public reset() {
this.inputFiles = [];
@@ -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[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);
@@ -750,7 +750,7 @@ module Harness {
emitResult = checker.emitFiles();
}
var errors: MinimalDiagnostic[] = [];
var errors: HarnessDiagnostic[] = [];
program.getDiagnostics().concat(checker.getDiagnostics()).concat(emitResult ? emitResult.errors : []).forEach(err => {
// TODO: new compiler formats errors after this point to add . and newlines so we'll just do it manually for now
errors.push(getMinimalDiagnostic(err));
@@ -768,20 +768,43 @@ module Harness {
}
}
export function getMinimalDiagnostic(err: ts.Diagnostic): MinimalDiagnostic {
export function getMinimalDiagnostic(err: ts.Diagnostic): HarnessDiagnostic {
var errorLineInfo = err.file ? err.file.getLineAndCharacterFromPosition(err.start) : { line: 0, character: 0 };
return { filename: err.file && err.file.filename, start: err.start, end: err.start + err.length, line: errorLineInfo.line, character: errorLineInfo.character, message: err.messageText };
return {
filename: err.file && err.file.filename,
start: err.start,
end: err.start + err.length,
line: errorLineInfo.line,
character: errorLineInfo.character,
message: err.messageText,
category: ts.DiagnosticCategory[err.category].toLowerCase(),
code: err.code
};
}
export function minimalDiagnosticsToString(diagnostics: HarnessDiagnostic[]) {
// This is basically copied from tsc.ts's reportError to replicate what tsc does
var errorOutput = "";
ts.forEach(diagnostics, diagnotic => {
if (diagnotic.filename) {
errorOutput += diagnotic.filename + "(" + diagnotic.line + "," + diagnotic.character + "): ";
}
errorOutput += diagnotic.category + " TS" + diagnotic.code + ": " + diagnotic.message + sys.newLine;
});
return errorOutput;
}
export function getErrorBaseline(inputFiles: { unitName: string; content: string }[],
diagnostics: MinimalDiagnostic[]
diagnostics: HarnessDiagnostic[]
) {
var outputLines: string[] = [];
// Count up all the errors we find so we don't miss any
var totalErrorsReported = 0;
function outputErrorText(error: Harness.Compiler.MinimalDiagnostic) {
function outputErrorText(error: Harness.Compiler.HarnessDiagnostic) {
var errLines = RunnerBase.removeFullPaths(error.message)
.split('\n')
.map(s => s.length > 0 && s.charAt(s.length - 1) === '\r' ? s.substr(0, s.length - 1) : s)
@@ -901,13 +924,15 @@ module Harness {
//harnessCompiler.compileString(code, unitName, callback);
}
export interface MinimalDiagnostic {
export interface HarnessDiagnostic {
filename: string;
start: number;
end: number;
line: number;
character: number;
message: string;
category: string;
code: number;
}
export interface GeneratedFile {
@@ -935,13 +960,13 @@ module Harness {
/** Contains the code and errors of a compilation and some helper methods to check its status. */
export class CompilerResult {
public files: GeneratedFile[] = [];
public errors: MinimalDiagnostic[] = [];
public errors: HarnessDiagnostic[] = [];
public declFilesCode: GeneratedFile[] = [];
public sourceMaps: GeneratedFile[] = [];
public sourceMapRecord: string;
/** @param fileResults an array of strings for the fileName and an ITextWriter with its code */
constructor(fileResults: GeneratedFile[], errors: MinimalDiagnostic[], sourceMapRecordLines: string[]) {
constructor(fileResults: GeneratedFile[], errors: HarnessDiagnostic[], sourceMapRecordLines: string[]) {
var lines: string[] = [];
fileResults.forEach(emittedFile => {
+20 -55
View File
@@ -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;
}
+2 -4
View File
@@ -173,8 +173,6 @@ module Playback {
var results = logArray.filter(e => pathsAreEquivalent(e.path, expectedPath, wrapper));
if (results.length === 0) {
if (defaultValue === undefined) {
console.log('Resolved path: ' + wrapper.resolvePath(expectedPath));
console.log('Filenames were: ' + logArray.map(x => x.path).join(', '));
throw new Error('No matching result in log array for path: ' + expectedPath);
} else {
return defaultValue;
@@ -191,7 +189,7 @@ module Playback {
}
function noOpReplay(name: string) {
console.log("Swallowed write operation during replay: " + name);
//console.log("Swallowed write operation during replay: " + name);
}
export function wrapSystem(underlying: System): PlaybackSystem {
@@ -257,7 +255,7 @@ module Playback {
wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)(
(path) => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path: path }),
memoize((path) => findResultByFields(replayLog.pathsResolved, { path: path }, replayLog.currentDirectory ? replayLog.currentDirectory + '/' + path : path)));
memoize((path) => findResultByFields(replayLog.pathsResolved, { path: path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + '/' + path : ts.normalizeSlashes(path))));
wrapper.readFile = recordReplay(wrapper.readFile, underlying)(
(path) => callAndRecord(underlying.readFile(path), recordLog.filesRead, { path: path, codepage: 0 }),
+2 -16
View File
@@ -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");
}
}
@@ -293,27 +293,13 @@ class ProjectRunner extends RunnerBase {
}
function getErrorsBaseline(compilerResult: CompileProjectFilesResult) {
// This is copied from tc.ts's reportError to replicate what tc does
var errors = "";
for (var i = 0; i < compilerResult.errors.length; i++) {
var error = compilerResult.errors[i];
// TODO(jfreeman): Remove assert
ts.Debug.assert(error.messageText.indexOf("{NL}") < 0);
if (error.file) {
var loc = error.file.getLineAndCharacterFromPosition(error.start);
errors += error.file.filename + "(" + loc.line + "," + loc.character + "): " + error.messageText + sys.newLine;
}
else {
errors += error.messageText + sys.newLine;
}
}
var inputFiles = ts.map(ts.filter(compilerResult.program.getSourceFiles(),
sourceFile => sourceFile.filename !== "lib.d.ts"),
sourceFile => {
return { unitName: sourceFile.filename, content: sourceFile.text };
});
var diagnostics = ts.map(compilerResult.errors, error => Harness.Compiler.getMinimalDiagnostic(error));
var errors = Harness.Compiler.minimalDiagnosticsToString(diagnostics);
errors += sys.newLine + sys.newLine + Harness.Compiler.getErrorBaseline(inputFiles, diagnostics);
return errors;
+69 -113
View File
@@ -5,27 +5,6 @@
/// <reference path='..\compiler\commandLineParser.ts'/>
module RWC {
class RWCEmitter implements Harness.Compiler.IEmitterIOHost {
public outputs: { [filename: string]: string; } = {};
constructor() { }
writeFile(path: string, contents: string, writeByteOrderMark: boolean) {
if (path in this.outputs) throw new Error('Emitter attempted to write to "' + path + '" twice');
this.outputs[path] = contents;
}
directoryExists(s: string) {
return false;
}
fileExists(s: string) {
return true;
}
resolvePath(s: string) {
return s;
}
}
function runWithIOLog(ioLog: IOLog, fn: () => void) {
var oldSys = sys;
@@ -41,32 +20,26 @@ module RWC {
}
}
function collateOutputs(emitterIOHost: RWCEmitter, fnTest: (s: string) => {}, clean?: (s: string) => string) {
function collateOutputs(outputFiles: Harness.Compiler.GeneratedFile[], clean?: (s: string) => string) {
// Collect, test, and sort the filenames
var files: string[] = [];
for (var fn in emitterIOHost.outputs) {
if (emitterIOHost.outputs.hasOwnProperty(fn) && fnTest(fn)) {
files.push(fn);
}
}
function cleanName(fn: string) {
var lastSlash = Harness.Path.switchToForwardSlashes(fn).lastIndexOf('/');
return fn.substr(lastSlash + 1).toLowerCase();
}
files.sort((a, b) => cleanName(a).localeCompare(cleanName(b)));
outputFiles.sort((a, b) => cleanName(a.fileName).localeCompare(cleanName(b.fileName)));
// Emit them
var result = '';
files.forEach(fn => {
ts.forEach(outputFiles, outputFile => {
// Some extra spacing if this isn't the first file
if (result.length) result = result + '\r\n\r\n';
// Filename header + content
result = result + '/*====== ' + fn + ' ======*/\r\n';
result = result + '/*====== ' + outputFile.fileName + ' ======*/\r\n';
if (clean) {
result = result + clean(emitterIOHost.outputs[fn]);
result = result + clean(outputFile.code);
} else {
result = result + emitterIOHost.outputs[fn];
result = result + outputFile.code;
}
});
return result;
@@ -86,90 +59,54 @@ module RWC {
});
});
var emitterIOHost = new RWCEmitter();
var inputFiles: { unitName: string; content: string; }[] = [];
var otherFiles: { unitName: string; content: string; }[] = [];
var compilerResult: Harness.Compiler.CompilerResult;
it('can compile', () => {
runWithIOLog(ioLog, () => {
harnessCompiler.reset();
var inputList: string[] = opts.filenames;
var noDefaultLib = false;
var libPath = Harness.IO.directoryName(sys.getExecutingFilePath()) + '/lib.d.ts';
if (!opts.options.noResolve) {
var filemap: any = {};
var host: ts.CompilerHost = {
getCurrentDirectory: () => sys.getCurrentDirectory(),
getCancellationToken: (): any => undefined,
getSourceFile: (fileName, languageVersion) => {
var fileContents: string;
try {
if (libPath === fileName) {
fileContents = Harness.IO.readFile(Harness.libFolder + "lib.d.ts");
}
else {
fileContents = sys.readFile(fileName);
}
}
catch (e) {
// Leave fileContents undefined;
}
return ts.createSourceFile(fileName, fileContents, languageVersion);
},
getDefaultLibFilename: () => libPath,
writeFile: (fn, contents) => emitterIOHost.writeFile(fn, contents, false),
getCanonicalFileName: ts.getCanonicalFileName,
useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
getNewLine: () => sys.newLine
};
var resolvedProgram = ts.createProgram(opts.filenames, opts.options, host);
resolvedProgram.getSourceFiles().forEach(sourceFile => {
noDefaultLib = noDefaultLib || sourceFile.hasNoDefaultLib;
if (inputList.indexOf(sourceFile.filename) === -1) {
inputList.push(sourceFile.filename);
}
});
}
if (!opts.options.noLib && !noDefaultLib) {
inputList.push(libPath);
}
harnessCompiler.reset();
harnessCompiler.setCompilerSettingsFromOptions(opts.options);
// Load the files
inputList.forEach((item: string) => {
var resolvedPath = libPath === item ? item : Harness.Path.switchToForwardSlashes(sys.resolvePath(item));
try {
if (libPath === item) {
var content = Harness.IO.readFile(Harness.libFolder + "lib.d.ts");
}
else {
var content = sys.readFile(resolvedPath);
}
}
catch (e) {
// Leave content undefined.
}
harnessCompiler.addInputFile({ unitName: resolvedPath, content: content });
ts.forEach(opts.filenames, fileName => {
inputFiles.push(getHarnessCompilerInputUnit(fileName));
});
harnessCompiler.setCompilerOptions();
if (!opts.options.noLib) {
// Find the lib.d.ts file in the input file and add it to the input files list
var libFile = ts.forEach(ioLog.filesRead, fileRead=> Harness.isLibraryFile(fileRead.path) ? fileRead.path : undefined);
if (libFile) {
inputFiles.push(getHarnessCompilerInputUnit(libFile));
}
}
ts.forEach(ioLog.filesRead, fileRead => {
var resolvedPath = Harness.Path.switchToForwardSlashes(sys.resolvePath(fileRead.path));
var inInputList = ts.forEach(inputFiles, inputFile=> inputFile.unitName === resolvedPath);
if (!inInputList) {
// Add the file to other files
otherFiles.push(getHarnessCompilerInputUnit(fileRead.path));
}
});
// do not use lib since we shouldnt be reading any files that arent in the ioLog
opts.options.noLib = true;
// Emit the results
harnessCompiler.emitAll(emitterIOHost);
var compilationErrors = harnessCompiler.reportCompilationErrors();
// Create an error baseline
compilationErrors.forEach(err => {
if (err.filename) {
errors += err.filename + ' (' + err.line + "," + err.character + "): " + err.message + '\r\n';
}
else {
errors += err.message + '\r\n';
}
});
harnessCompiler.compileFiles(inputFiles, otherFiles, compileResult => {
compilerResult = compileResult;
}, /*settingsCallback*/ undefined, opts.options);
});
function getHarnessCompilerInputUnit(fileName: string) {
var resolvedPath = Harness.Path.switchToForwardSlashes(sys.resolvePath(fileName));
try {
var content = sys.readFile(resolvedPath);
}
catch (e) {
// Leave content undefined.
}
return { unitName: resolvedPath, content: content };
}
});
// Baselines
@@ -178,27 +115,46 @@ module RWC {
it('has the expected emitted code', () => {
Harness.Baseline.runBaseline('has the expected emitted code', baseName + '.output.js', () => {
return collateOutputs(emitterIOHost, fn => Harness.Compiler.isJS(fn), s => SyntacticCleaner.clean(s));
return collateOutputs(compilerResult.files, s => SyntacticCleaner.clean(s));
}, false, baselineOpts);
});
it('has the expected declaration file content', () => {
Harness.Baseline.runBaseline('has the expected declaration file content', baseName + '.d.ts', () => {
var result = collateOutputs(emitterIOHost, fn => Harness.Compiler.isDTS(fn));
return result.length > 0 ? result : null;
if (compilerResult.errors.length || !compilerResult.declFilesCode.length) {
return null;
}
return collateOutputs(compilerResult.declFilesCode);
}, false, baselineOpts);
});
it('has the expected source maps', () => {
Harness.Baseline.runBaseline('has the expected source maps', baseName + '.map', () => {
var result = collateOutputs(emitterIOHost, fn => fn.substr(fn.length - '.map'.length) === '.map');
return result.length > 0 ? result : null;
if (!compilerResult.sourceMaps.length) {
return null;
}
return collateOutputs(compilerResult.sourceMaps);
}, false, baselineOpts);
});
it('has correct source map record', () => {
if (compilerResult.sourceMapRecord) {
Harness.Baseline.runBaseline('has correct source map record', baseName + '.sourcemap.txt', () => {
return compilerResult.sourceMapRecord;
}, false, baselineOpts);
}
});
it('has the expected errors', () => {
Harness.Baseline.runBaseline('has the expected errors', baseName + '.errors.txt', () => {
return errors.length > 0 ? errors : null;
if (compilerResult.errors.length === 0) {
return null;
}
return Harness.Compiler.minimalDiagnosticsToString(compilerResult.errors) +
sys.newLine + sys.newLine +
Harness.Compiler.getErrorBaseline(inputFiles.concat(otherFiles), compilerResult.errors);
}, false, baselineOpts);
});
+37 -80
View File
@@ -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;
}
}
}
}
+50 -59
View File
@@ -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;
+2 -2
View File
@@ -763,7 +763,7 @@ module TypeScript {
var start = new Date().getTime();
var accessors = PullHelpers.getGetterAndSetterFunction(funcDecl, this.semanticInfoChain);
TypeScript.declarationEmitGetAccessorFunctionTime += new Date().getTime();
TypeScript.declarationEmitGetAccessorFunctionTime += new Date().getTime() - start;
var comments: Comment[] = [];
if (accessors.getter) {
@@ -787,7 +787,7 @@ module TypeScript {
private emitMemberAccessorDeclaration(funcDecl: ISyntaxElement, modifiers: ISyntaxToken[], name: ISyntaxToken) {
var start = new Date().getTime();
var accessorSymbol = PullHelpers.getAccessorSymbol(funcDecl, this.semanticInfoChain);
TypeScript.declarationEmitGetAccessorFunctionTime += new Date().getTime();
TypeScript.declarationEmitGetAccessorFunctionTime += new Date().getTime() - start;
if (funcDecl.kind() === SyntaxKind.SetAccessor && accessorSymbol.getGetter()) {
// Setter is being used to emit the type info.
-20
View File
@@ -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;
}
}
+18 -23
View File
@@ -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;
+2 -2
View File
@@ -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;
+5
View File
@@ -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());
}
+278 -282
View File
@@ -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));
}
}
}
+398 -179
View File
@@ -25,7 +25,6 @@
/// <reference path='compiler\pathUtils.ts' />
module ts {
export interface Node {
getSourceFile(): SourceFile;
getChildCount(): number;
@@ -70,7 +69,8 @@ module ts {
export interface SourceFile {
getSourceUnit(): TypeScript.SourceUnitSyntax;
getSyntaxTree(): TypeScript.SyntaxTree;
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);
@@ -319,7 +319,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;
public identifiers: Map<string>;
@@ -332,6 +332,10 @@ module ts {
return this.getSyntaxTree().sourceUnit();
}
public getScriptSnapshot(): TypeScript.IScriptSnapshot {
return this.scriptSnapshot;
}
public getLineMap(): TypeScript.LineMap {
return this.getSyntaxTree().lineMap();
}
@@ -355,7 +359,7 @@ module ts {
return TypeScript.isDTSFile(this.filename);
}
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
@@ -390,7 +394,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;
@@ -399,11 +403,6 @@ module ts {
}
export interface Logger {
information(): boolean;
debug(): boolean;
warning(): boolean;
error(): boolean;
fatal(): boolean;
log(s: string): void;
}
@@ -413,7 +412,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;
@@ -425,9 +424,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[];
@@ -439,28 +435,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;
@@ -469,30 +467,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 {
@@ -513,14 +549,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 {
@@ -529,54 +565,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 {
@@ -664,7 +726,7 @@ module ts {
filename: string,
compilationSettings: CompilerOptions,
scriptSnapshot: TypeScript.IScriptSnapshot,
version: number,
version: string,
isOpen: boolean): SourceFile;
updateDocument(
@@ -672,7 +734,7 @@ module ts {
filename: string,
compilationSettings: CompilerOptions,
scriptSnapshot: TypeScript.IScriptSnapshot,
version: number,
version: string,
isOpen: boolean,
textChangeRange: TypeScript.TextChangeRange
): SourceFile;
@@ -790,7 +852,7 @@ module ts {
// Information about a specific host file.
interface HostFileInformation {
filename: string;
version: number;
version: string;
isOpen: boolean;
sourceText?: TypeScript.IScriptSnapshot;
}
@@ -899,7 +961,7 @@ module ts {
return fileNames;
}
public getVersion(filename: string): number {
public getVersion(filename: string): string {
return this.getEntry(filename).version;
}
@@ -915,14 +977,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);
}
}
@@ -931,11 +993,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);
@@ -950,7 +1011,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);
@@ -959,9 +1020,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);
@@ -972,9 +1034,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;
}
@@ -1009,7 +1070,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 {
@@ -1023,8 +1084,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);
@@ -1036,7 +1097,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;
}
@@ -1104,7 +1165,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);
}
@@ -1149,7 +1210,7 @@ module ts {
filename: string,
compilationSettings: CompilerOptions,
scriptSnapshot: TypeScript.IScriptSnapshot,
version: number,
version: string,
isOpen: boolean): SourceFile {
var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
@@ -1173,7 +1234,7 @@ module ts {
filename: string,
compilationSettings: CompilerOptions,
scriptSnapshot: TypeScript.IScriptSnapshot,
version: number,
version: string,
isOpen: boolean,
textChangeRange: TypeScript.TextChangeRange
): SourceFile {
@@ -1461,7 +1522,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);
@@ -1950,25 +2011,23 @@ 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, position);
if (!node) return undefined;
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;
@@ -1977,15 +2036,13 @@ module ts {
/// Goto definition
function getDefinitionAtPosition(filename: string, position: number): DefinitionInfo[]{
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[]) {
@@ -2055,11 +2112,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;
}
@@ -2456,12 +2512,15 @@ module ts {
}
function getReferenceEntry(node: Node): ReferenceEntry {
return {
fileName: node.getSourceFile().filename,
minChar: node.kind === SyntaxKind.StringLiteral ? node.getStart() + 1 : node.getStart(),
limChar: node.kind === SyntaxKind.StringLiteral ? node.getEnd() - 1 : node.getEnd(),
isWriteAccess: isWriteAccess(node)
};
var start = node.getStart();
var end = node.getEnd();
if (node.kind === SyntaxKind.StringLiteral) {
start += 1;
end -= 1;
}
return new ReferenceEntry(node.getSourceFile().filename, TypeScript.TextSpan.fromBounds(start, end), isWriteAccess(node));
}
function getMeaningFromDeclaration(node: Declaration): SearchMeaning {
@@ -2648,7 +2707,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();
@@ -2699,10 +2758,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) {
@@ -2713,15 +2771,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);
@@ -2768,41 +2824,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,
@@ -2810,7 +3027,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: getReferencesAtPosition,
getOccurrencesAtPosition: getOccurrencesAtPosition,
@@ -2818,15 +3036,16 @@ 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,
};
}
+104 -151
View File
@@ -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;
}
}
+69 -45
View File
@@ -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.
+24 -9
View File
@@ -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();
}
+7 -5
View File
@@ -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();
}
}
+4
View File
@@ -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;
}
@@ -20,6 +20,7 @@ Foo();
//// [callOverloads1.js]
var Foo = (function () {
function Foo(x) {
// WScript.Echo("Constructor function has executed");
}
Foo.prototype.bar1 = function () {
};
@@ -28,6 +28,7 @@ Foo();
//// [callOverloads2.js]
var Foo = (function () {
function Foo(x) {
// WScript.Echo("Constructor function has executed");
}
Foo.prototype.bar1 = function () {
};
@@ -21,6 +21,7 @@ Foo("s");
//// [callOverloads3.js]
var Foo = (function () {
function Foo(x) {
// WScript.Echo("Constructor function has executed");
}
Foo.prototype.bar1 = function () {
};
@@ -21,6 +21,7 @@ Foo("s");
//// [callOverloads4.js]
var Foo = (function () {
function Foo(x) {
// WScript.Echo("Constructor function has executed");
}
Foo.prototype.bar1 = function () {
};
@@ -22,6 +22,7 @@ Foo("s");
//// [callOverloads5.js]
var Foo = (function () {
function Foo(x) {
// WScript.Echo("Constructor function has executed");
}
Foo.prototype.bar1 = function (a) {
};
@@ -52,6 +52,8 @@ var Test1 = (function () {
this.field1 = field1;
this.messageHandler = function () {
console.log(field1); // But this should be error as the field1 will resolve to var field1
// but since this code would be generated inside constructor, in generated js
// it would resolve to private field1 and thats not what user intended here.
};
}
Test1.staticMessageHandler = function () {
@@ -25,6 +25,8 @@ var Test1 = (function () {
this.field1 = field1;
this.messageHandler = function () {
console.log(field1); // But this should be error as the field1 will resolve to var field1
// but since this code would be generated inside constructor, in generated js
// it would resolve to private field1 and thats not what user intended here.
};
}
return Test1;
+1
View File
@@ -16,6 +16,7 @@ var A = (function () {
function A() {
}
A.prototype.foo = function () {
/*WScript.Echo("Here!");*/
};
return A;
})();
@@ -63,6 +63,14 @@ class c8 {
}
var i8 = new c8();
var i8_c = c8;
class c9 {
constructor() {
/// This is some detached comment
// should emit this leading comment of } too
}
}
//// [commentsClass.js]
@@ -123,11 +131,20 @@ var c8 = (function () {
/** constructor comment
*/
function c8() {
/** constructor comment2
*/
}
return c8;
})();
var i8 = new c8();
var i8_c = c8;
var c9 = (function () {
function c9() {
/// This is some detached comment
// should emit this leading comment of } too
}
return c9;
})();
//// [commentsClass.d.ts]
@@ -178,3 +195,6 @@ declare class c8 {
}
declare var i8: c8;
declare var i8_c: typeof c8;
declare class c9 {
constructor();
}
@@ -130,3 +130,13 @@ var i8_c = c8;
>i8_c : typeof c8
>c8 : typeof c8
class c9 {
>c9 : c9
constructor() {
/// This is some detached comment
// should emit this leading comment of } too
}
}
+22 -1
View File
@@ -41,7 +41,19 @@ lambdaFoo = (a, b) => a * b; // This is trailing comment
/*leading comment*/(() => 0); //trailing comment
function blah4(/*1*/a: string/*2*/,/*3*/b: string/*4*/) {
}
}
function foo1() {
// should emit this
}
function foo2() {
/// This is some detached comment
// should emit this leading comment of } too
}
//// [commentsFunction.js]
/** This comment should appear for foo*/
@@ -79,6 +91,13 @@ lambdaFoo = function (a, b) { return a * b; }; // This is trailing comment
/*leading comment*/ (function () { return 0; }); //trailing comment
function blah4(/*1*/ a /*2*/, /*3*/ b /*4*/) {
}
function foo1() {
// should emit this
}
function foo2() {
/// This is some detached comment
// should emit this leading comment of } too
}
//// [commentsFunction.d.ts]
@@ -98,3 +117,5 @@ declare function blah(a: string): void;
declare function blah2(a: string): void;
declare function blah3(a: string): void;
declare function blah4(a: string, b: string): void;
declare function foo1(): void;
declare function foo2(): void;
@@ -110,3 +110,18 @@ function blah4(/*1*/a: string/*2*/,/*3*/b: string/*4*/) {
>a : string
>b : string
}
function foo1() {
>foo1 : () => void
// should emit this
}
function foo2() {
>foo2 : () => void
/// This is some detached comment
// should emit this leading comment of } too
}
@@ -66,6 +66,8 @@ function other2(x) {
var r7 = foo(function (a) { return a; }, function (b) { return b; }); // T => T
var r7b = foo(function (a) { return a; }, function (b) { return b; }); // {} => {}
var r8 = r7(null);
// BUG 835518
//var r9 = r7(new Date());
}
function foo2(a, b) {
var r;
@@ -54,4 +54,6 @@ function other3(arg) {
var b;
var r2 = foo(b);
var d = r2[1];
// BUG 821629
//var u: U = r2[1]; // ok
}
@@ -55,4 +55,6 @@ function other3(arg) {
var b;
var r2 = foo(b);
var d = r2['hm']; // ok
// BUG 821629
//var u: U = r2['hm']; // ok
}
@@ -37,6 +37,7 @@ function fn2(t, u, v) {
var r4 = u || u;
var r5 = u || v;
var r6 = u || v;
//var r7: T = u || v;
}
function fn3(t, u) {
var r1 = t || u;
@@ -11,6 +11,7 @@ var Foo = (function () {
function Foo() {
}
Foo.prototype.foo = function () {
//return 4;
};
return Foo;
})();
+1
View File
@@ -27,6 +27,7 @@ var MyClass = (function () {
return 42;
};
MyClass.prototype.SetCount = function (value) {
//
};
return MyClass;
})();
+1 -1
View File
@@ -1,2 +1,2 @@
//// [out-flag.js.map]
{"version":3,"file":"out-flag.js","sourceRoot":"","sources":["out-flag.ts"],"names":["MyClass","MyClass.constructor","MyClass.Count","MyClass.SetCount"],"mappings":"AAAA,eAAe;AAGf,AADA,oBAAoB;IACd,OAAO;IAAbA,SAAMA,OAAOA;IAYbC,CAACA;IAVGD,uBAAuBA;IAChBA,uBAAKA,GAAZA;QAEIE,MAAMA,CAACA,EAAEA,CAACA;IACdA,CAACA;IAEMF,0BAAQA,GAAfA,UAAgBA,KAAaA;IAG7BG,CAACA;IACLH,cAACA;AAADA,CAACA,AAZD,IAYC"}
{"version":3,"file":"out-flag.js","sourceRoot":"","sources":["out-flag.ts"],"names":["MyClass","MyClass.constructor","MyClass.Count","MyClass.SetCount"],"mappings":"AAAA,eAAe;AAGf,AADA,oBAAoB;IACd,OAAO;IAAbA,SAAMA,OAAOA;IAYbC,CAACA;IAVGD,uBAAuBA;IAChBA,uBAAKA,GAAZA;QAEIE,MAAMA,CAACA,EAAEA,CAACA;IACdA,CAACA;IAEMF,0BAAQA,GAAfA,UAAgBA,KAAaA;QAEzBG,EAAEA;IACNA,CAACA;IACLH,cAACA;AAADA,CAACA,AAZD,IAYC"}
@@ -143,17 +143,25 @@ sourceFile:out-flag.ts
4 >Emitted(10, 44) Source(12, 21) + SourceIndex(0) name (MyClass)
5 >Emitted(10, 49) Source(12, 34) + SourceIndex(0) name (MyClass)
---
>>> //
1 >^^^^^^^^
2 > ^^
1 >)
> {
>
2 > //
1 >Emitted(11, 9) Source(14, 9) + SourceIndex(0) name (MyClass.SetCount)
2 >Emitted(11, 11) Source(14, 11) + SourceIndex(0) name (MyClass.SetCount)
---
>>> };
1 >^^^^
2 > ^
3 > ^^^^^^^^^^^^^^^->
1 >)
> {
> //
1 >
>
2 > }
1 >Emitted(11, 5) Source(15, 5) + SourceIndex(0) name (MyClass.SetCount)
2 >Emitted(11, 6) Source(15, 6) + SourceIndex(0) name (MyClass.SetCount)
1 >Emitted(12, 5) Source(15, 5) + SourceIndex(0) name (MyClass.SetCount)
2 >Emitted(12, 6) Source(15, 6) + SourceIndex(0) name (MyClass.SetCount)
---
>>> return MyClass;
1->^^^^
@@ -161,8 +169,8 @@ sourceFile:out-flag.ts
1->
>
2 > }
1->Emitted(12, 5) Source(16, 1) + SourceIndex(0) name (MyClass)
2 >Emitted(12, 19) Source(16, 2) + SourceIndex(0) name (MyClass)
1->Emitted(13, 5) Source(16, 1) + SourceIndex(0) name (MyClass)
2 >Emitted(13, 19) Source(16, 2) + SourceIndex(0) name (MyClass)
---
>>>})();
1 >
@@ -186,9 +194,9 @@ sourceFile:out-flag.ts
> //
> }
> }
1 >Emitted(13, 1) Source(16, 1) + SourceIndex(0) name (MyClass)
2 >Emitted(13, 2) Source(16, 2) + SourceIndex(0) name (MyClass)
3 >Emitted(13, 2) Source(4, 1) + SourceIndex(0)
4 >Emitted(13, 6) Source(16, 2) + SourceIndex(0)
1 >Emitted(14, 1) Source(16, 1) + SourceIndex(0) name (MyClass)
2 >Emitted(14, 2) Source(16, 2) + SourceIndex(0) name (MyClass)
3 >Emitted(14, 2) Source(4, 1) + SourceIndex(0)
4 >Emitted(14, 6) Source(16, 2) + SourceIndex(0)
---
>>>//# sourceMappingURL=out-flag.js.map
@@ -1,6 +1,6 @@
decl.ts(1,26): Cannot find external module './foo/bar.js'.
decl.ts(2,26): Cannot find external module 'baz'.
decl.ts(3,26): Cannot find external module './baz'.
decl.ts(1,26): error TS2307: Cannot find external module './foo/bar.js'.
decl.ts(2,26): error TS2307: Cannot find external module 'baz'.
decl.ts(3,26): error TS2307: Cannot find external module './baz'.
==== decl.ts (3 errors) ====
@@ -1,6 +1,6 @@
decl.ts(1,26): Cannot find external module './foo/bar.js'.
decl.ts(2,26): Cannot find external module 'baz'.
decl.ts(3,26): Cannot find external module './baz'.
decl.ts(1,26): error TS2307: Cannot find external module './foo/bar.js'.
decl.ts(2,26): error TS2307: Cannot find external module 'baz'.
decl.ts(3,26): error TS2307: Cannot find external module './baz'.
==== decl.ts (3 errors) ====
@@ -1,4 +1,4 @@
in2.d.ts(1,8): Duplicate identifier 'a'.
in2.d.ts(1,8): error TS2300: Duplicate identifier 'a'.
==== decl.d.ts (0 errors) ====
@@ -1,4 +1,4 @@
in2.d.ts(1,8): Duplicate identifier 'a'.
in2.d.ts(1,8): error TS2300: Duplicate identifier 'a'.
==== decl.d.ts (0 errors) ====
@@ -1,4 +1,4 @@
internal2.ts(2,2): Import declarations in an internal module cannot reference an external module.
internal2.ts(2,2): error TS1147: Import declarations in an internal module cannot reference an external module.
==== internal2.ts (1 errors) ====
@@ -1,4 +1,4 @@
internal2.ts(2,2): Import declarations in an internal module cannot reference an external module.
internal2.ts(2,2): error TS1147: Import declarations in an internal module cannot reference an external module.
==== internal2.ts (1 errors) ====
@@ -1,5 +1,5 @@
Option mapRoot cannot be specified without specifying sourcemap option.
Option sourceRoot cannot be specified without specifying sourcemap option.
error TS5038: Option mapRoot cannot be specified without specifying sourcemap option.
error TS5039: Option sourceRoot cannot be specified without specifying sourcemap option.
!!! Option mapRoot cannot be specified without specifying sourcemap option.
@@ -1,5 +1,5 @@
Option mapRoot cannot be specified without specifying sourcemap option.
Option sourceRoot cannot be specified without specifying sourcemap option.
error TS5038: Option mapRoot cannot be specified without specifying sourcemap option.
error TS5039: Option sourceRoot cannot be specified without specifying sourcemap option.
!!! Option mapRoot cannot be specified without specifying sourcemap option.
@@ -1,4 +1,4 @@
Option mapRoot cannot be specified without specifying sourcemap option.
error TS5038: Option mapRoot cannot be specified without specifying sourcemap option.
!!! Option mapRoot cannot be specified without specifying sourcemap option.
@@ -1,4 +1,4 @@
Option mapRoot cannot be specified without specifying sourcemap option.
error TS5038: Option mapRoot cannot be specified without specifying sourcemap option.
!!! Option mapRoot cannot be specified without specifying sourcemap option.
@@ -1,4 +1,4 @@
test1.ts(2,2): Import declarations in an internal module cannot reference an external module.
test1.ts(2,2): error TS1147: Import declarations in an internal module cannot reference an external module.
==== test1.ts (1 errors) ====
@@ -1,4 +1,4 @@
test1.ts(2,2): Import declarations in an internal module cannot reference an external module.
test1.ts(2,2): error TS1147: Import declarations in an internal module cannot reference an external module.
==== test1.ts (1 errors) ====
@@ -1,4 +1,4 @@
test1.ts(3,2): Import declarations in an internal module cannot reference an external module.
test1.ts(3,2): error TS1147: Import declarations in an internal module cannot reference an external module.
==== test1.ts (1 errors) ====
@@ -1,4 +1,4 @@
test1.ts(3,2): Import declarations in an internal module cannot reference an external module.
test1.ts(3,2): error TS1147: Import declarations in an internal module cannot reference an external module.
==== test1.ts (1 errors) ====
@@ -1,12 +1,12 @@
Cannot find global type 'Array'.
Cannot find global type 'Boolean'.
Cannot find global type 'Function'.
Cannot find global type 'IArguments'.
Cannot find global type 'Number'.
Cannot find global type 'Object'.
Cannot find global type 'RegExp'.
Cannot find global type 'String'.
test.ts(3,8): Cannot find name 'Array'.
error TS2318: Cannot find global type 'Array'.
error TS2318: Cannot find global type 'Boolean'.
error TS2318: Cannot find global type 'Function'.
error TS2318: Cannot find global type 'IArguments'.
error TS2318: Cannot find global type 'Number'.
error TS2318: Cannot find global type 'Object'.
error TS2318: Cannot find global type 'RegExp'.
error TS2318: Cannot find global type 'String'.
test.ts(3,8): error TS2304: Cannot find name 'Array'.
!!! Cannot find global type 'Array'.
@@ -1,12 +1,12 @@
Cannot find global type 'Array'.
Cannot find global type 'Boolean'.
Cannot find global type 'Function'.
Cannot find global type 'IArguments'.
Cannot find global type 'Number'.
Cannot find global type 'Object'.
Cannot find global type 'RegExp'.
Cannot find global type 'String'.
test.ts(3,8): Cannot find name 'Array'.
error TS2318: Cannot find global type 'Array'.
error TS2318: Cannot find global type 'Boolean'.
error TS2318: Cannot find global type 'Function'.
error TS2318: Cannot find global type 'IArguments'.
error TS2318: Cannot find global type 'Number'.
error TS2318: Cannot find global type 'Object'.
error TS2318: Cannot find global type 'RegExp'.
error TS2318: Cannot find global type 'String'.
test.ts(3,8): error TS2304: Cannot find name 'Array'.
!!! Cannot find global type 'Array'.
@@ -1,5 +1,5 @@
testGlo.ts(2,5): Import declarations in an internal module cannot reference an external module.
testGlo.ts(21,5): Import declarations in an internal module cannot reference an external module.
testGlo.ts(2,5): error TS1147: Import declarations in an internal module cannot reference an external module.
testGlo.ts(21,5): error TS1147: Import declarations in an internal module cannot reference an external module.
==== testGlo.ts (2 errors) ====
@@ -1,5 +1,5 @@
testGlo.ts(2,5): Import declarations in an internal module cannot reference an external module.
testGlo.ts(21,5): Import declarations in an internal module cannot reference an external module.
testGlo.ts(2,5): error TS1147: Import declarations in an internal module cannot reference an external module.
testGlo.ts(21,5): error TS1147: Import declarations in an internal module cannot reference an external module.
==== testGlo.ts (2 errors) ====
@@ -1,5 +1,5 @@
test.ts(5,5): Import declarations in an internal module cannot reference an external module.
test.ts(24,5): Import declarations in an internal module cannot reference an external module.
test.ts(5,5): error TS1147: Import declarations in an internal module cannot reference an external module.
test.ts(24,5): error TS1147: Import declarations in an internal module cannot reference an external module.
==== test.ts (2 errors) ====
@@ -1,5 +1,5 @@
test.ts(5,5): Import declarations in an internal module cannot reference an external module.
test.ts(24,5): Import declarations in an internal module cannot reference an external module.
test.ts(5,5): error TS1147: Import declarations in an internal module cannot reference an external module.
test.ts(24,5): error TS1147: Import declarations in an internal module cannot reference an external module.
==== test.ts (2 errors) ====
@@ -1,5 +1,5 @@
test.ts(2,5): Import declarations in an internal module cannot reference an external module.
test.ts(42,5): Import declarations in an internal module cannot reference an external module.
test.ts(2,5): error TS1147: Import declarations in an internal module cannot reference an external module.
test.ts(42,5): error TS1147: Import declarations in an internal module cannot reference an external module.
==== test.ts (2 errors) ====
@@ -1,5 +1,5 @@
test.ts(2,5): Import declarations in an internal module cannot reference an external module.
test.ts(42,5): Import declarations in an internal module cannot reference an external module.
test.ts(2,5): error TS1147: Import declarations in an internal module cannot reference an external module.
test.ts(42,5): error TS1147: Import declarations in an internal module cannot reference an external module.
==== test.ts (2 errors) ====
@@ -1,4 +1,4 @@
m'ain.d.ts(1,1): File 'li.ts' not found.
m'ain.d.ts(1,1): error TS6053: File 'li.ts' not found.
==== li'b/class'A.d.ts (0 errors) ====
@@ -1,4 +1,4 @@
m'ain.d.ts(1,1): File 'li.ts' not found.
m'ain.d.ts(1,1): error TS6053: File 'li.ts' not found.
==== li'b/class'A.d.ts (0 errors) ====
@@ -1,4 +1,4 @@
Option sourceRoot cannot be specified without specifying sourcemap option.
error TS5039: Option sourceRoot cannot be specified without specifying sourcemap option.
!!! Option sourceRoot cannot be specified without specifying sourcemap option.
@@ -1,4 +1,4 @@
Option sourceRoot cannot be specified without specifying sourcemap option.
error TS5039: Option sourceRoot cannot be specified without specifying sourcemap option.
!!! Option sourceRoot cannot be specified without specifying sourcemap option.
@@ -1,5 +1,5 @@
main.ts(2,1): File 'nonExistingFile1.ts' not found.
main.ts(3,1): File 'nonExistingFile2.ts' not found.
main.ts(2,1): error TS6053: File 'nonExistingFile1.ts' not found.
main.ts(3,1): error TS6053: File 'nonExistingFile2.ts' not found.
==== main.ts (2 errors) ====
@@ -1,5 +1,5 @@
main.ts(2,1): File 'nonExistingFile1.ts' not found.
main.ts(3,1): File 'nonExistingFile2.ts' not found.
main.ts(2,1): error TS6053: File 'nonExistingFile1.ts' not found.
main.ts(3,1): error TS6053: File 'nonExistingFile2.ts' not found.
==== main.ts (2 errors) ====
+1
View File
@@ -22,6 +22,7 @@ var MyClass = (function () {
return 42;
},
set: function (value) {
//
},
enumerable: true,
configurable: true
+1 -1
View File
@@ -1,2 +1,2 @@
//// [properties.js.map]
{"version":3,"file":"properties.js","sourceRoot":"","sources":["properties.ts"],"names":["MyClass","MyClass.constructor","MyClass.Count"],"mappings":"AACA,IAAM,OAAO;IAAbA,SAAMA,OAAOA;IAWbC,CAACA;IATGD,sBAAWA,0BAAKA;aAAhBA;YAEIE,MAAMA,CAACA,EAAEA,CAACA;QACdA,CAACA;aAEDF,UAAiBA,KAAaA;QAG9BE,CAACA;;;OALAF;IAMLA,cAACA;AAADA,CAACA,AAXD,IAWC"}
{"version":3,"file":"properties.js","sourceRoot":"","sources":["properties.ts"],"names":["MyClass","MyClass.constructor","MyClass.Count"],"mappings":"AACA,IAAM,OAAO;IAAbA,SAAMA,OAAOA;IAWbC,CAACA;IATGD,sBAAWA,0BAAKA;aAAhBA;YAEIE,MAAMA,CAACA,EAAEA,CAACA;QACdA,CAACA;aAEDF,UAAiBA,KAAaA;YAE1BE,EAAEA;QACNA,CAACA;;;OALAF;IAMLA,cAACA;AAADA,CAACA,AAXD,IAWC"}
@@ -111,17 +111,25 @@ sourceFile:properties.ts
2 >Emitted(8, 24) Source(9, 22) + SourceIndex(0) name (MyClass)
3 >Emitted(8, 29) Source(9, 35) + SourceIndex(0) name (MyClass)
---
>>> //
1 >^^^^^^^^^^^^
2 > ^^
1 >)
> {
>
2 > //
1 >Emitted(9, 13) Source(11, 9) + SourceIndex(0) name (MyClass.Count)
2 >Emitted(9, 15) Source(11, 11) + SourceIndex(0) name (MyClass.Count)
---
>>> },
1 >^^^^^^^^
2 > ^
3 > ^^^^^^^^^^^^^^^^^->
1 >)
> {
> //
1 >
>
2 > }
1 >Emitted(9, 9) Source(12, 5) + SourceIndex(0) name (MyClass.Count)
2 >Emitted(9, 10) Source(12, 6) + SourceIndex(0) name (MyClass.Count)
1 >Emitted(10, 9) Source(12, 5) + SourceIndex(0) name (MyClass.Count)
2 >Emitted(10, 10) Source(12, 6) + SourceIndex(0) name (MyClass.Count)
---
>>> enumerable: true,
>>> configurable: true
@@ -129,7 +137,7 @@ sourceFile:properties.ts
1->^^^^^^^
2 > ^^^^^^^^^^^^^->
1->
1->Emitted(12, 8) Source(7, 6) + SourceIndex(0) name (MyClass)
1->Emitted(13, 8) Source(7, 6) + SourceIndex(0) name (MyClass)
---
>>> return MyClass;
1->^^^^
@@ -142,8 +150,8 @@ sourceFile:properties.ts
> }
>
2 > }
1->Emitted(13, 5) Source(13, 1) + SourceIndex(0) name (MyClass)
2 >Emitted(13, 19) Source(13, 2) + SourceIndex(0) name (MyClass)
1->Emitted(14, 5) Source(13, 1) + SourceIndex(0) name (MyClass)
2 >Emitted(14, 19) Source(13, 2) + SourceIndex(0) name (MyClass)
---
>>>})();
1 >
@@ -166,9 +174,9 @@ sourceFile:properties.ts
> //
> }
> }
1 >Emitted(14, 1) Source(13, 1) + SourceIndex(0) name (MyClass)
2 >Emitted(14, 2) Source(13, 2) + SourceIndex(0) name (MyClass)
3 >Emitted(14, 2) Source(2, 1) + SourceIndex(0)
4 >Emitted(14, 6) Source(13, 2) + SourceIndex(0)
1 >Emitted(15, 1) Source(13, 1) + SourceIndex(0) name (MyClass)
2 >Emitted(15, 2) Source(13, 2) + SourceIndex(0) name (MyClass)
3 >Emitted(15, 2) Source(2, 1) + SourceIndex(0)
4 >Emitted(15, 6) Source(13, 2) + SourceIndex(0)
---
>>>//# sourceMappingURL=properties.js.map
@@ -0,0 +1,44 @@
//// [tests/cases/compiler/sourceMapWithMultipleFilesWithCopyright.ts] ////
//// [a.ts]
/*--------------------------------------------------------------------------
Copyright
---------------------------------------------------------------------------*/
var x = {
a: 10,
b: 20
};
//// [b.ts]
/*--------------------------------------------------------------------------
Copyright
---------------------------------------------------------------------------*/
///<reference path="a.ts"/>
var y = x;
//// [a.js]
/*--------------------------------------------------------------------------
Copyright
---------------------------------------------------------------------------*/
var x = {
a: 10,
b: 20
};
/*--------------------------------------------------------------------------
Copyright
---------------------------------------------------------------------------*/
///<reference path="a.ts"/>
var y = x;
//# sourceMappingURL=a.js.map
//// [a.d.ts]
declare var x: {
a: number;
b: number;
};
declare var y: {
a: number;
b: number;
};
@@ -0,0 +1,2 @@
//// [a.js.map]
{"version":3,"file":"a.js","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/b.ts"],"names":[],"mappings":"AAAA;;6EAE6E;AAE7E,IAAI,CAAC,GAAG;IACJ,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;CACR,CAAC;ACPF;;6EAE6E;AAG7E,AADA,2BAA2B;IACvB,CAAC,GAAG,CAAC,CAAC"}
@@ -0,0 +1,134 @@
===================================================================
JsFile: a.js
mapUrl: a.js.map
sourceRoot:
sources: tests/cases/compiler/a.ts,tests/cases/compiler/b.ts
===================================================================
-------------------------------------------------------------------
emittedFile:a.js
sourceFile:tests/cases/compiler/a.ts
-------------------------------------------------------------------
>>>/*--------------------------------------------------------------------------
1 >
2 >^^^^^^^^^^->
1 >
1 >Emitted(1, 1) Source(1, 1) + SourceIndex(0)
---
>>>Copyright
>>>---------------------------------------------------------------------------*/
1->^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1->/*--------------------------------------------------------------------------
>Copyright
>---------------------------------------------------------------------------*/
1->Emitted(3, 78) Source(3, 78) + SourceIndex(0)
---
>>>var x = {
1 >
2 >^^^^
3 > ^
4 > ^^^
5 > ^^^->
1 >
>
>
2 >var
3 > x
4 > =
1 >Emitted(4, 1) Source(5, 1) + SourceIndex(0)
2 >Emitted(4, 5) Source(5, 5) + SourceIndex(0)
3 >Emitted(4, 6) Source(5, 6) + SourceIndex(0)
4 >Emitted(4, 9) Source(5, 9) + SourceIndex(0)
---
>>> a: 10,
1->^^^^
2 > ^
3 > ^^
4 > ^^
5 > ^->
1->{
>
2 > a
3 > :
4 > 10
1->Emitted(5, 5) Source(6, 5) + SourceIndex(0)
2 >Emitted(5, 6) Source(6, 6) + SourceIndex(0)
3 >Emitted(5, 8) Source(6, 8) + SourceIndex(0)
4 >Emitted(5, 10) Source(6, 10) + SourceIndex(0)
---
>>> b: 20
1->^^^^
2 > ^
3 > ^^
4 > ^^
1->,
>
2 > b
3 > :
4 > 20
1->Emitted(6, 5) Source(7, 5) + SourceIndex(0)
2 >Emitted(6, 6) Source(7, 6) + SourceIndex(0)
3 >Emitted(6, 8) Source(7, 8) + SourceIndex(0)
4 >Emitted(6, 10) Source(7, 10) + SourceIndex(0)
---
>>>};
1 >^
2 > ^
3 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^->
1 >
>}
2 > ;
1 >Emitted(7, 2) Source(8, 2) + SourceIndex(0)
2 >Emitted(7, 3) Source(8, 3) + SourceIndex(0)
---
-------------------------------------------------------------------
emittedFile:a.js
sourceFile:tests/cases/compiler/b.ts
-------------------------------------------------------------------
>>>/*--------------------------------------------------------------------------
1->
2 >^^^^^^^^^^->
1->
1->Emitted(8, 1) Source(1, 1) + SourceIndex(1)
---
>>>Copyright
>>>---------------------------------------------------------------------------*/
1->^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1->/*--------------------------------------------------------------------------
>Copyright
>---------------------------------------------------------------------------*/
1->Emitted(10, 78) Source(3, 78) + SourceIndex(1)
---
>>>///<reference path="a.ts"/>
1 >
2 >
3 >^^^^^^^^^^^^^^^^^^^^^^^^^^^
1 >
>
>///<reference path="a.ts"/>
>
2 >
3 >///<reference path="a.ts"/>
1 >Emitted(11, 1) Source(6, 1) + SourceIndex(1)
2 >Emitted(11, 1) Source(5, 1) + SourceIndex(1)
3 >Emitted(11, 28) Source(5, 28) + SourceIndex(1)
---
>>>var y = x;
1 >^^^^
2 > ^
3 > ^^^
4 > ^
5 > ^
6 > ^^^^^^^^^^^^^^^^^^->
1 >
>var
2 > y
3 > =
4 > x
5 > ;
1 >Emitted(12, 5) Source(6, 5) + SourceIndex(1)
2 >Emitted(12, 6) Source(6, 6) + SourceIndex(1)
3 >Emitted(12, 9) Source(6, 9) + SourceIndex(1)
4 >Emitted(12, 10) Source(6, 10) + SourceIndex(1)
5 >Emitted(12, 11) Source(6, 11) + SourceIndex(1)
---
>>>//# sourceMappingURL=a.js.map
@@ -0,0 +1,30 @@
=== tests/cases/compiler/b.ts ===
/*--------------------------------------------------------------------------
Copyright
---------------------------------------------------------------------------*/
///<reference path="a.ts"/>
var y = x;
>y : { a: number; b: number; }
>x : { a: number; b: number; }
=== tests/cases/compiler/a.ts ===
/*--------------------------------------------------------------------------
Copyright
---------------------------------------------------------------------------*/
var x = {
>x : { a: number; b: number; }
>{
a: 10,
b: 20
} : { a: number; b: number; }
a: 10,
>a : number
b: 20
>b : number
};
+8
View File
@@ -65,3 +65,11 @@ class c8 {
}
var i8 = new c8();
var i8_c = c8;
class c9 {
constructor() {
/// This is some detached comment
// should emit this leading comment of } too
}
}
+12 -1
View File
@@ -43,4 +43,15 @@ lambdaFoo = (a, b) => a * b; // This is trailing comment
/*leading comment*/(() => 0); //trailing comment
function blah4(/*1*/a: string/*2*/,/*3*/b: string/*4*/) {
}
}
function foo1() {
// should emit this
}
function foo2() {
/// This is some detached comment
// should emit this leading comment of } too
}
@@ -0,0 +1,20 @@
// @out: a.js
// @sourcemap: true
// @declaration: true
// @Filename: a.ts
/*--------------------------------------------------------------------------
Copyright
---------------------------------------------------------------------------*/
var x = {
a: 10,
b: 20
};
// @Filename: b.ts
/*--------------------------------------------------------------------------
Copyright
---------------------------------------------------------------------------*/
///<reference path="a.ts"/>
var y = x;
+3
View File
@@ -0,0 +1,3 @@
//// // [|TODO|]
debugger;
verify.todoCommentsInCurrentFile(["TODO"]);
+6
View File
@@ -0,0 +1,6 @@
//// /*
//// [|todo 1|]
//// [|hack 2|]
//// */
debugger;
verify.todoCommentsInCurrentFile(["TODO", "HACK"]);
+6
View File
@@ -0,0 +1,6 @@
//// /*
//// [|TODO(jason) 1|]
//// [|HACK 2|]
//// */
debugger;
verify.todoCommentsInCurrentFile(["TODO(jason)", "HACK"]);
+6
View File
@@ -0,0 +1,6 @@
//// /*
//// [|TODO(jason) 1|]
//// [|HACK 2|]
//// */
debugger;
verify.todoCommentsInCurrentFile(["HACK", "TODO(jason)"]);
+4
View File
@@ -0,0 +1,4 @@
//// TODO
debugger;
verify.todoCommentsInCurrentFile(["TODO"]);
+3
View File
@@ -0,0 +1,3 @@
//// BAR // [|TODO|]
debugger;
verify.todoCommentsInCurrentFile(["TODO"]);
+3
View File
@@ -0,0 +1,3 @@
//// "// HACK 1";
debugger;
verify.todoCommentsInCurrentFile(["TODO(jason)", "HACK"]);
+3
View File
@@ -0,0 +1,3 @@
//// //// [|HACK 1|]
debugger;
verify.todoCommentsInCurrentFile(["TODO(jason)", "HACK"]);
+3
View File
@@ -0,0 +1,3 @@
//// /**** [|HACK 1 |]*/ a
debugger;
verify.todoCommentsInCurrentFile(["TODO(jason)", "HACK"]);
+3
View File
@@ -0,0 +1,3 @@
//// // not TODO
debugger;
verify.todoCommentsInCurrentFile(["TODO"]);
+3
View File
@@ -0,0 +1,3 @@
//// // [|TODO with stuff|]
debugger;
verify.todoCommentsInCurrentFile(["TODO"]);
+3
View File
@@ -0,0 +1,3 @@
//// // TODOnomatch
debugger;
verify.todoCommentsInCurrentFile(["TODO"]);

Some files were not shown because too many files have changed in this diff Show More