diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index acb7aaaed26..53a20a99fd5 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -122,6 +122,8 @@ module ts { let_declarations_can_only_be_declared_inside_a_block: { code: 1157, category: DiagnosticCategory.Error, key: "'let' declarations can only be declared inside a block." }, Invalid_template_literal_expected: { code: 1158, category: DiagnosticCategory.Error, key: "Invalid template literal; expected '}'" }, Tagged_templates_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1159, category: DiagnosticCategory.Error, key: "Tagged templates are only available when targeting ECMAScript 6 and higher." }, + Unterminated_template_literal: { code: 1160, category: DiagnosticCategory.Error, key: "Unterminated template literal." }, + Unterminated_regular_expression_literal: { code: 1161, category: DiagnosticCategory.Error, key: "Unterminated regular expression literal." }, A_object_member_cannot_be_declared_optional: { code: 1160, category: DiagnosticCategory.Error, key: "A object member cannot be declared optional." }, 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." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 9145b345b2d..78c60f2276e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -479,6 +479,14 @@ "category": "Error", "code": 1159 }, + "Unterminated template literal.": { + "category": "Error", + "code": 1160 + }, + "Unterminated regular expression literal.": { + "category": "Error", + "code": 1161 + }, "A object member cannot be declared optional.": { "category": "Error", diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 24ff3378d59..0647d61f24d 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -553,7 +553,7 @@ module ts { while (true) { if (pos >= len) { result += text.substring(start, pos); - error(Diagnostics.Unexpected_end_of_text); + error(Diagnostics.Unterminated_string_literal); break; } var ch = text.charCodeAt(pos); @@ -593,7 +593,7 @@ module ts { while (true) { if (pos >= len) { contents += text.substring(start, pos); - error(Diagnostics.Unexpected_end_of_text); + error(Diagnostics.Unterminated_template_literal); resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail; break; } @@ -1066,19 +1066,19 @@ module ts { var inEscape = false; var inCharacterClass = false; while (true) { - // If we've hit EOF without closing off the regex, - // simply return the token we originally parsed. + // If we reach the end of a file, or hit a newline, then this is an unterminated + // regex. Report error and return what we have so far. if (p >= len) { - return token; + error(Diagnostics.Unterminated_regular_expression_literal) + break; } var ch = text.charCodeAt(p); - - // Line breaks are not permissible in the middle of a RegExp. if (isLineBreak(ch)) { - return token; + error(Diagnostics.Unterminated_regular_expression_literal) + break; } - + if (inEscape) { // Parsing an escape character; // reset the flag and just advance to the next char. @@ -1087,6 +1087,7 @@ module ts { else if (ch === CharacterCodes.slash && !inCharacterClass) { // A slash within a character class is permissible, // but in general it signals the end of the regexp literal. + p++; break; } else if (ch === CharacterCodes.openBracket) { @@ -1100,8 +1101,8 @@ module ts { } p++; } - p++; - while (isIdentifierPart(text.charCodeAt(p))) { + + while (p < len && isIdentifierPart(text.charCodeAt(p))) { p++; } pos = p; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index ffb0ed16cb8..144cc9745d9 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -215,7 +215,7 @@ module FourSlash { } public setCancelled(numberOfCalls: number = 0): void { - TypeScript.Debug.assert(numberOfCalls >= 0); + ts.Debug.assert(numberOfCalls >= 0); this.numberOfCallsBeforeCancellation = numberOfCalls; } @@ -239,7 +239,7 @@ module FourSlash { // This function creates IScriptSnapshot object for testing getPreProcessedFileInfo // Return object may lack some functionalities for other purposes. - function createScriptSnapShot(sourceText: string): TypeScript.IScriptSnapshot { + function createScriptSnapShot(sourceText: string): ts.IScriptSnapshot { return { getText: (start: number, end: number) => { return sourceText.substr(start, end - start); @@ -250,8 +250,8 @@ module FourSlash { getLineStartPositions: () => { return []; }, - getChangeRange: (oldSnapshot: TypeScript.IScriptSnapshot) => { - return undefined; + getChangeRange: (oldSnapshot: ts.IScriptSnapshot) => { + return undefined; } }; } @@ -262,7 +262,7 @@ module FourSlash { private languageService: ts.LanguageService; // A reference to the language service's compiler state's compiler instance - private compiler: () => { getSyntaxTree(fileName: string): TypeScript.SyntaxTree; getSourceUnit(fileName: string): TypeScript.SourceUnitSyntax; }; + private compiler: () => { getSyntaxTree(fileName: string): ts.SourceFile }; // The current caret position in the active file public currentCaretPosition = 0; @@ -403,8 +403,9 @@ module FourSlash { public goToPosition(pos: number) { this.currentCaretPosition = pos; - var lineCharPos = TypeScript.LineMap1.fromString(this.getCurrentFileContent()).getLineAndCharacterFromPosition(pos); - this.scenarioActions.push(''); + var lineStarts = ts.computeLineStarts(this.getCurrentFileContent()); + var lineCharPos = ts.getLineAndCharacterOfPosition(lineStarts, pos); + this.scenarioActions.push(''); } public moveCaretRight(count = 1) { @@ -1017,7 +1018,7 @@ module FourSlash { private alignmentForExtraInfo = 50; - private spanInfoToString(pos: number, spanInfo: TypeScript.TextSpan, prefixString: string) { + private spanInfoToString(pos: number, spanInfo: ts.TextSpan, prefixString: string) { var resultString = "SpanInfo: " + JSON.stringify(spanInfo); if (spanInfo) { var spanString = this.activeFile.content.substr(spanInfo.start(), spanInfo.length()); @@ -1034,7 +1035,7 @@ module FourSlash { return resultString; } - private baselineCurrentFileLocations(getSpanAtPos: (pos: number) => TypeScript.TextSpan): string { + private baselineCurrentFileLocations(getSpanAtPos: (pos: number) => ts.TextSpan): string { var fileLineMap = ts.computeLineStarts(this.activeFile.content); var nextLine = 0; var resultString = ""; @@ -1748,14 +1749,14 @@ module FourSlash { public verifySemanticClassifications(expected: { classificationType: string; text: string }[]) { var actual = this.languageService.getSemanticClassifications(this.activeFile.fileName, - new TypeScript.TextSpan(0, this.activeFile.content.length)); + new ts.TextSpan(0, this.activeFile.content.length)); this.verifyClassifications(expected, actual); } public verifySyntacticClassifications(expected: { classificationType: string; text: string }[]) { var actual = this.languageService.getSyntacticClassifications(this.activeFile.fileName, - new TypeScript.TextSpan(0, this.activeFile.content.length)); + new ts.TextSpan(0, this.activeFile.content.length)); this.verifyClassifications(expected, actual); } @@ -1789,7 +1790,7 @@ module FourSlash { 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); + var actualCommentSpan = new ts.TextSpan(actualComment.position, actualComment.message.length); if (expectedSpan.start !== actualCommentSpan.start() || expectedSpan.end !== actualCommentSpan.end()) { this.raiseError('verifyOutliningSpans failed - span ' + (i + 1) + ' expected: (' + expectedSpan.start + ',' + expectedSpan.end + '), actual: (' + actualCommentSpan.start() + ',' + actualCommentSpan.end() + ')'); @@ -2240,11 +2241,12 @@ module FourSlash { (fn, contents) => result = contents, ts.ScriptTarget.Latest, sys.useCaseSensitiveFileNames); - var program = ts.createProgram([Harness.Compiler.fourslashFilename, fileName], { out: "fourslashTestOutput.js" }, host); + // TODO (drosen): We need to enforce checking on these tests. + var program = ts.createProgram([Harness.Compiler.fourslashFilename, fileName], { out: "fourslashTestOutput.js", noResolve: true }, host); var checker = ts.createTypeChecker(program, /*fullTypeCheckMode*/ true); checker.checkProgram(); - var errs = checker.getDiagnostics(program.getSourceFile(fileName)); + var errs = program.getDiagnostics().concat(checker.getDiagnostics()); if (errs.length > 0) { throw new Error('Error compiling ' + fileName + ': ' + errs.map(e => e.messageText).join('\r\n')); } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index d5eaa3828a1..aee0ef3c534 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -585,7 +585,7 @@ module Harness { return defaultLibSourceFile; } // Don't throw here -- the compiler might be looking for a test that actually doesn't exist as part of the TC - return null; + return undefined; } }, getDefaultLibFilename: () => defaultLibFileName, diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 6163dfd0e79..d3082a17ba2 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -4,8 +4,8 @@ module Harness.LanguageService { export class ScriptInfo { public version: number = 1; - public editRanges: { length: number; textChangeRange: TypeScript.TextChangeRange; }[] = []; - public lineMap: TypeScript.LineMap = null; + public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = []; + public lineMap: number[] = null; constructor(public fileName: string, public content: string, public isOpen = true) { this.setContent(content); @@ -13,7 +13,7 @@ module Harness.LanguageService { private setContent(content: string): void { this.content = content; - this.lineMap = TypeScript.LineMap1.fromString(content); + this.lineMap = ts.computeLineStarts(content); } public updateContent(content: string): void { @@ -32,30 +32,30 @@ module Harness.LanguageService { // Store edit range + new length of script this.editRanges.push({ length: this.content.length, - textChangeRange: new TypeScript.TextChangeRange( - TypeScript.TextSpan.fromBounds(minChar, limChar), newText.length) + textChangeRange: new ts.TextChangeRange( + ts.TextSpan.fromBounds(minChar, limChar), newText.length) }); // Update version # this.version++; } - public getTextChangeRangeBetweenVersions(startVersion: number, endVersion: number): TypeScript.TextChangeRange { + public getTextChangeRangeBetweenVersions(startVersion: number, endVersion: number): ts.TextChangeRange { if (startVersion === endVersion) { // No edits! - return TypeScript.TextChangeRange.unchanged; + return ts.TextChangeRange.unchanged; } var initialEditRangeIndex = this.editRanges.length - (this.version - startVersion); var lastEditRangeIndex = this.editRanges.length - (this.version - endVersion); var entries = this.editRanges.slice(initialEditRangeIndex, lastEditRangeIndex); - return TypeScript.TextChangeRange.collapseChangesAcrossMultipleVersions(entries.map(e => e.textChangeRange)); + return ts.TextChangeRange.collapseChangesAcrossMultipleVersions(entries.map(e => e.textChangeRange)); } } class ScriptSnapshotShim implements ts.ScriptSnapshotShim { - private lineMap: TypeScript.LineMap = null; + private lineMap: number[] = null; private textSnapshot: string; private version: number; @@ -74,10 +74,10 @@ module Harness.LanguageService { public getLineStartPositions(): string { if (this.lineMap === null) { - this.lineMap = TypeScript.LineMap1.fromString(this.textSnapshot); + this.lineMap = ts.computeLineStarts(this.textSnapshot); } - return JSON.stringify(this.lineMap.lineStarts()); + return JSON.stringify(this.lineMap); } public getChangeRange(oldScript: ts.ScriptSnapshotShim): string { @@ -108,7 +108,7 @@ module Harness.LanguageService { public acquireDocument( fileName: string, compilationSettings: ts.CompilerOptions, - scriptSnapshot: TypeScript.IScriptSnapshot, + scriptSnapshot: ts.IScriptSnapshot, version: string, isOpen: boolean): ts.SourceFile { return ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, version, isOpen); @@ -118,10 +118,10 @@ module Harness.LanguageService { document: ts.SourceFile, fileName: string, compilationSettings: ts.CompilerOptions, - scriptSnapshot: TypeScript.IScriptSnapshot, + scriptSnapshot: ts.IScriptSnapshot, version: string, isOpen: boolean, - textChangeRange: TypeScript.TextChangeRange + textChangeRange: ts.TextChangeRange ): ts.SourceFile { return document.update(scriptSnapshot, version, isOpen, textChangeRange); } @@ -263,13 +263,13 @@ module Harness.LanguageService { } /** Parse file given its source text */ - public parseSourceText(fileName: string, sourceText: TypeScript.IScriptSnapshot): TypeScript.SourceUnitSyntax { - return TypeScript.Parser.parse(fileName, TypeScript.SimpleText.fromScriptSnapshot(sourceText), ts.ScriptTarget.Latest, TypeScript.isDTSFile(fileName)).sourceUnit(); + public parseSourceText(fileName: string, sourceText: ts.IScriptSnapshot): ts.SourceFile { + return ts.createSourceFile(fileName, sourceText.getText(0, sourceText.getLength()), ts.ScriptTarget.Latest, "1", true); } /** Parse a file on disk given its fileName */ public parseFile(fileName: string) { - var sourceText = TypeScript.ScriptSnapshot.fromString(Harness.IO.readFile(fileName)); + var sourceText = ts.ScriptSnapshot.fromString(Harness.IO.readFile(fileName)); return this.parseSourceText(fileName, sourceText); } @@ -283,22 +283,22 @@ module Harness.LanguageService { assert.isTrue(line >= 1); assert.isTrue(col >= 1); - return script.lineMap.getPosition(line - 1, col - 1); + return ts.getPositionFromLineAndCharacter(script.lineMap, line, col); } /** * @param line 0 based index * @param col 0 based index */ - public positionToZeroBasedLineCol(fileName: string, position: number): TypeScript.ILineAndCharacter { + public positionToZeroBasedLineCol(fileName: string, position: number): ts.LineAndCharacter { var script: ScriptInfo = this.fileNameToScript[fileName]; assert.isNotNull(script); - var result = script.lineMap.getLineAndCharacterFromPosition(position); + var result = ts.getLineAndCharacterOfPosition(script.lineMap, position); - assert.isTrue(result.line() >= 0); - assert.isTrue(result.character() >= 0); - return { line: result.line(), character: result.character() }; + assert.isTrue(result.line >= 1); + assert.isTrue(result.character >= 1); + return { line: result.line - 1, character: result.character - 1 }; } /** Verify that applying edits to sourceFileName result in the content of the file baselineFileName */ diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index f8688b3c479..7867751a96f 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -38,25 +38,25 @@ module ts.BreakpointResolver { return spanInNode(tokenAtLocation); function textSpan(startNode: Node, endNode?: Node) { - return TypeScript.TextSpan.fromBounds(startNode.getStart(), (endNode || startNode).getEnd()); + return TextSpan.fromBounds(startNode.getStart(), (endNode || startNode).getEnd()); } - function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TypeScript.TextSpan { + function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan { if (node && lineOfPosition === sourceFile.getLineAndCharacterFromPosition(node.getStart()).line) { return spanInNode(node); } return spanInNode(otherwiseOnNode); } - function spanInPreviousNode(node: Node): TypeScript.TextSpan { + function spanInPreviousNode(node: Node): TextSpan { return spanInNode(findPrecedingToken(node.pos, sourceFile)); } - function spanInNextNode(node: Node): TypeScript.TextSpan { + function spanInNextNode(node: Node): TextSpan { return spanInNode(findNextToken(node, node.parent)); } - function spanInNode(node: Node): TypeScript.TextSpan { + function spanInNode(node: Node): TextSpan { if (node) { if (isExpression(node)) { if (node.parent.kind === SyntaxKind.DoStatement) { @@ -256,7 +256,7 @@ module ts.BreakpointResolver { } } - function spanInVariableDeclaration(variableDeclaration: VariableDeclaration): TypeScript.TextSpan { + function spanInVariableDeclaration(variableDeclaration: VariableDeclaration): TextSpan { // If declaration of for in statement, just set the span in parent if (variableDeclaration.parent.kind === SyntaxKind.ForInStatement) { return spanInNode(variableDeclaration.parent); @@ -301,7 +301,7 @@ module ts.BreakpointResolver { !!(parameter.flags & NodeFlags.Public) || !!(parameter.flags & NodeFlags.Private); } - function spanInParameterDeclaration(parameter: ParameterDeclaration): TypeScript.TextSpan { + function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan { if (canHaveSpanInParameterDeclaration(parameter)) { return textSpan(parameter); } @@ -324,7 +324,7 @@ module ts.BreakpointResolver { (functionDeclaration.parent.kind === SyntaxKind.ClassDeclaration && functionDeclaration.kind !== SyntaxKind.Constructor); } - function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TypeScript.TextSpan { + function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TextSpan { // No breakpoints in the function signature if (!functionDeclaration.body) { return undefined; @@ -339,7 +339,7 @@ module ts.BreakpointResolver { return spanInNode(functionDeclaration.body); } - function spanInFunctionBlock(block: Block): TypeScript.TextSpan { + function spanInFunctionBlock(block: Block): TextSpan { var nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken(); if (canFunctionHaveSpanInWholeDeclaration(block.parent)) { return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock); @@ -348,7 +348,7 @@ module ts.BreakpointResolver { return spanInNode(nodeForSpanInBlock); } - function spanInBlock(block: Block): TypeScript.TextSpan { + function spanInBlock(block: Block): TextSpan { switch (block.parent.kind) { case SyntaxKind.ModuleDeclaration: if (getModuleInstanceState(block.parent) !== ModuleInstanceState.Instantiated) { @@ -370,7 +370,7 @@ module ts.BreakpointResolver { return spanInNode(block.statements[0]); } - function spanInForStatement(forStatement: ForStatement): TypeScript.TextSpan { + function spanInForStatement(forStatement: ForStatement): TextSpan { if (forStatement.declarations) { return spanInNode(forStatement.declarations[0]); } @@ -386,7 +386,7 @@ module ts.BreakpointResolver { } // Tokens: - function spanInOpenBraceToken(node: Node): TypeScript.TextSpan { + function spanInOpenBraceToken(node: Node): TextSpan { switch (node.parent.kind) { case SyntaxKind.EnumDeclaration: var enumDeclaration = node.parent; @@ -404,7 +404,7 @@ module ts.BreakpointResolver { return spanInNode(node.parent); } - function spanInCloseBraceToken(node: Node): TypeScript.TextSpan { + function spanInCloseBraceToken(node: Node): TextSpan { switch (node.parent.kind) { case SyntaxKind.ModuleBlock: // If this is not instantiated module block no bp span @@ -439,7 +439,7 @@ module ts.BreakpointResolver { } } - function spanInOpenParenToken(node: Node): TypeScript.TextSpan { + function spanInOpenParenToken(node: Node): TextSpan { if (node.parent.kind === SyntaxKind.DoStatement) { // Go to while keyword and do action instead return spanInPreviousNode(node); @@ -449,7 +449,7 @@ module ts.BreakpointResolver { return spanInNode(node.parent); } - function spanInCloseParenToken(node: Node): TypeScript.TextSpan { + function spanInCloseParenToken(node: Node): TextSpan { // Is this close paren token of parameter list, set span in previous token switch (node.parent.kind) { case SyntaxKind.FunctionExpression: @@ -473,7 +473,7 @@ module ts.BreakpointResolver { return spanInNode(node.parent); } - function spanInColonToken(node: Node): TypeScript.TextSpan { + function spanInColonToken(node: Node): TextSpan { // Is this : specifying return annotation of the function declaration if (isAnyFunction(node.parent) || node.parent.kind === SyntaxKind.PropertyAssignment) { return spanInPreviousNode(node); @@ -482,7 +482,7 @@ module ts.BreakpointResolver { return spanInNode(node.parent); } - function spanInGreaterThanOrLessThanToken(node: Node): TypeScript.TextSpan { + function spanInGreaterThanOrLessThanToken(node: Node): TextSpan { if (node.parent.kind === SyntaxKind.TypeAssertion) { return spanInNode((node.parent).operand); } @@ -490,7 +490,7 @@ module ts.BreakpointResolver { return spanInNode(node.parent); } - function spanInWhileKeyword(node: Node): TypeScript.TextSpan { + function spanInWhileKeyword(node: Node): TextSpan { if (node.parent.kind === SyntaxKind.DoStatement) { // Set span on while expression return textSpan(node, findNextToken((node.parent).expression, node.parent)); diff --git a/src/services/formatting.ts b/src/services/formatting.ts index dbe85fc4c64..91a3a362fda 100644 --- a/src/services/formatting.ts +++ b/src/services/formatting.ts @@ -834,7 +834,7 @@ module ts.formatting { } function newTextChange(start: number, len: number, newText: string): TextChange { - return { span: new TypeScript.TextSpan(start, len), newText: newText } + return { span: new TextSpan(start, len), newText: newText } } function recordDelete(start: number, len: number) { diff --git a/src/services/formatting/references.ts b/src/services/formatting/references.ts index 3d19b33d821..9f4b7e37436 100644 --- a/src/services/formatting/references.ts +++ b/src/services/formatting/references.ts @@ -13,6 +13,7 @@ // limitations under the License. // +/// /// /// /// diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 4b42591936e..2485945df0b 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -24,7 +24,7 @@ module ts.formatting { return name; } } - throw new Error(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Unknown_rule, null)); + throw new Error("Unknown rule"); } [name: string]: any; diff --git a/src/services/formatting/rulesProvider.ts b/src/services/formatting/rulesProvider.ts index 1469e86971b..7ad1b65400c 100644 --- a/src/services/formatting/rulesProvider.ts +++ b/src/services/formatting/rulesProvider.ts @@ -22,7 +22,7 @@ module ts.formatting { private activeRules: Rule[]; private rulesMap: RulesMap; - constructor(private logger: TypeScript.Logger) { + constructor(private logger: Logger) { this.globalRules = new Rules(); } diff --git a/src/services/formatting/tokenSpan.ts b/src/services/formatting/tokenSpan.ts index 95f9bab3eee..1d8173a8227 100644 --- a/src/services/formatting/tokenSpan.ts +++ b/src/services/formatting/tokenSpan.ts @@ -16,7 +16,7 @@ /// module ts.formatting { - export class TokenSpan extends TypeScript.TextSpan { + export class TokenSpan extends TextSpan { constructor(public kind: SyntaxKind, start: number, length: number) { super(start, length); } diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index ca06d40fa88..c0ec80c98ea 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -1,5 +1,4 @@ /// -/// module ts.NavigationBar { export function getNavigationBarItems(sourceFile: SourceFile): ts.NavigationBarItem[] { @@ -257,7 +256,7 @@ module ts.NavigationBar { return !text || text.trim() === ""; } - function getNavigationBarItem(text: string, kind: string, kindModifiers: string, spans: TypeScript.TextSpan[], childItems: ts.NavigationBarItem[] = [], indent: number = 0): ts.NavigationBarItem { + function getNavigationBarItem(text: string, kind: string, kindModifiers: string, spans: TextSpan[], childItems: NavigationBarItem[] = [], indent: number = 0): NavigationBarItem { if (isEmpty(text)) { return undefined; } @@ -424,8 +423,8 @@ module ts.NavigationBar { function getNodeSpan(node: Node) { return node.kind === SyntaxKind.SourceFile - ? TypeScript.TextSpan.fromBounds(node.getFullStart(), node.getEnd()) - : TypeScript.TextSpan.fromBounds(node.getStart(), node.getEnd()); + ? TextSpan.fromBounds(node.getFullStart(), node.getEnd()) + : TextSpan.fromBounds(node.getStart(), node.getEnd()); } function getTextOfNode(node: Node): string { diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index aaaedb735ea..27f75b8d20e 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -24,8 +24,8 @@ module ts { * @param autoCollapse Whether or not this region should be automatically collapsed when * the 'Collapse to Definitions' command is invoked. */ - textSpan: TypeScript.TextSpan; - hintSpan: TypeScript.TextSpan; + textSpan: TextSpan; + hintSpan: TextSpan; bannerText: string; autoCollapse: boolean; } @@ -38,8 +38,8 @@ module ts { function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean) { if (hintSpanNode && startElement && endElement) { var span: OutliningSpan = { - textSpan: TypeScript.TextSpan.fromBounds(startElement.pos, endElement.end), - hintSpan: TypeScript.TextSpan.fromBounds(hintSpanNode.getStart(), hintSpanNode.end), + textSpan: TextSpan.fromBounds(startElement.pos, endElement.end), + hintSpan: TextSpan.fromBounds(hintSpanNode.getStart(), hintSpanNode.end), bannerText: collapseText, autoCollapse: autoCollapse }; @@ -86,7 +86,7 @@ module ts { else { // Block was a standalone block. In this case we want to only collapse // the span of the block, independent of any parent span. - var span = TypeScript.TextSpan.fromBounds(n.getStart(), n.end); + var span = TextSpan.fromBounds(n.getStart(), n.end); elements.push({ textSpan: span, hintSpan: span, diff --git a/src/services/resources/diagnosticCode.generated.ts b/src/services/resources/diagnosticCode.generated.ts index 1b140105b16..e5878978fcc 100644 --- a/src/services/resources/diagnosticCode.generated.ts +++ b/src/services/resources/diagnosticCode.generated.ts @@ -5,7 +5,7 @@ module TypeScript { warning_TS_0_1: "warning TS{0}: {1}", Unrecognized_escape_sequence: "Unrecognized escape sequence.", Unexpected_character_0: "Unexpected character {0}.", - Missing_close_quote_character: "Missing close quote character.", + Unterminated_string_literal: "Unterminated string literal.", Identifier_expected: "Identifier expected.", _0_keyword_expected: "'{0}' keyword expected.", _0_expected: "'{0}' expected.", @@ -97,6 +97,8 @@ module TypeScript { Template_literal_cannot_be_used_as_an_element_name: "Template literal cannot be used as an element name.", Computed_property_names_cannot_be_used_here: "Computed property names cannot be used here.", yield_expression_must_be_contained_within_a_generator_declaration: "'yield' expression must be contained within a generator declaration.", + Unterminated_regular_expression_literal: "Unterminated regular expression literal.", + Unterminated_template_literal: "Unterminated template literal.", Duplicate_identifier_0: "Duplicate identifier '{0}'.", The_name_0_does_not_exist_in_the_current_scope: "The name '{0}' does not exist in the current scope.", The_name_0_does_not_refer_to_a_value: "The name '{0}' does not refer to a value.", diff --git a/src/services/resources/diagnosticInformationMap.generated.ts b/src/services/resources/diagnosticInformationMap.generated.ts index 8e911f469ef..d6597a008df 100644 --- a/src/services/resources/diagnosticInformationMap.generated.ts +++ b/src/services/resources/diagnosticInformationMap.generated.ts @@ -6,7 +6,7 @@ module TypeScript { "warning TS{0}: {1}": { "code": 1, "category": DiagnosticCategory.NoPrefix }, "Unrecognized escape sequence.": { "code": 1000, "category": DiagnosticCategory.Error }, "Unexpected character {0}.": { "code": 1001, "category": DiagnosticCategory.Error }, - "Missing close quote character.": { "code": 1002, "category": DiagnosticCategory.Error }, + "Unterminated string literal.": { "code": 1002, "category": DiagnosticCategory.Error }, "Identifier expected.": { "code": 1003, "category": DiagnosticCategory.Error }, "'{0}' keyword expected.": { "code": 1004, "category": DiagnosticCategory.Error }, "'{0}' expected.": { "code": 1005, "category": DiagnosticCategory.Error }, @@ -99,6 +99,8 @@ module TypeScript { "Template literal cannot be used as an element name.": { "code": 1111, "category": DiagnosticCategory.Error }, "Computed property names cannot be used here.": { "code": 1112, "category": DiagnosticCategory.Error }, "'yield' expression must be contained within a generator declaration.": { "code": 1113, "category": DiagnosticCategory.Error }, + "Unterminated regular expression literal.": { "code": 1114, "category": DiagnosticCategory.Error }, + "Unterminated template literal.": { "code": 1115, "category": DiagnosticCategory.Error }, "Duplicate identifier '{0}'.": { "code": 2000, "category": DiagnosticCategory.Error }, "The name '{0}' does not exist in the current scope.": { "code": 2001, "category": DiagnosticCategory.Error }, "The name '{0}' does not refer to a value.": { "code": 2002, "category": DiagnosticCategory.Error }, diff --git a/src/services/resources/diagnosticMessages.json b/src/services/resources/diagnosticMessages.json index c238568eac6..724edbd8f3b 100644 --- a/src/services/resources/diagnosticMessages.json +++ b/src/services/resources/diagnosticMessages.json @@ -15,7 +15,7 @@ "category": "Error", "code": 1001 }, - "Missing close quote character.": { + "Unterminated string literal.": { "category": "Error", "code": 1002 }, @@ -383,6 +383,14 @@ "category": "Error", "code": 1113 }, + "Unterminated regular expression literal.": { + "category": "Error", + "code": 1114 + }, + "Unterminated template literal.": { + "category": "Error", + "code": 1115 + }, "Duplicate identifier '{0}'.": { "category": "Error", "code": 2000 diff --git a/src/services/services.ts b/src/services/services.ts index 90635354a3d..9345d84b7c1 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4,7 +4,7 @@ /// /// -/// +/// /// /// /// @@ -13,17 +13,6 @@ /// /// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// - module ts { export interface Node { getSourceFile(): SourceFile; @@ -70,11 +59,72 @@ module ts { } export interface SourceFile { - getScriptSnapshot(): TypeScript.IScriptSnapshot; + getScriptSnapshot(): IScriptSnapshot; getNamedDeclarations(): Declaration[]; - update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile; + update(scriptSnapshot: IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TextChangeRange): SourceFile; } + /** + * Represents an immutable snapshot of a script at a specified time.Once acquired, the + * snapshot is observably immutable. i.e. the same calls with the same parameters will return + * the same values. + */ + export interface IScriptSnapshot { + /** Gets a portion of the script snapshot specified by [start, end). */ + getText(start: number, end: number): string; + + /** Gets the length of this script snapshot. */ + getLength(): number; + + /** + * This call returns the array containing the start position of every line. + * i.e."[0, 10, 55]". TODO: consider making this optional. The language service could + * always determine this (albeit in a more expensive manner). + */ + getLineStartPositions(): number[]; + + /** + * Gets the TextChangeRange that describe how the text changed between this text and + * an older version. This information is used by the incremental parser to determine + * what sections of the script need to be re-parsed. 'undefined' 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 re - parsed. + */ + getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange; + } + + export module ScriptSnapshot { + class StringScriptSnapshot implements IScriptSnapshot { + private _lineStartPositions: number[] = undefined; + + constructor(private text: string) { + } + + public getText(start: number, end: number): string { + return this.text.substring(start, end); + } + + public getLength(): number { + return this.text.length; + } + + public getLineStartPositions(): number[] { + if (!this._lineStartPositions) { + this._lineStartPositions = computeLineStarts(this.text); + } + + return this._lineStartPositions; + } + + public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange { + throw new Error("not yet implemented"); + } + } + + export function fromString(text: string): IScriptSnapshot { + return new StringScriptSnapshot(text); + } + } export interface PreProcessedFileInfo { referencedFiles: FileReference[]; importedFiles: FileReference[]; @@ -682,10 +732,10 @@ module ts { public languageVersion: ScriptTarget; public identifiers: Map; - private scriptSnapshot: TypeScript.IScriptSnapshot; + private scriptSnapshot: IScriptSnapshot; private namedDeclarations: Declaration[]; - public getScriptSnapshot(): TypeScript.IScriptSnapshot { + public getScriptSnapshot(): IScriptSnapshot { return this.scriptSnapshot; } @@ -761,28 +811,28 @@ module ts { return this.namedDeclarations; } - public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile { + public update(scriptSnapshot: IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TextChangeRange): SourceFile { if (textChangeRange && Debug.shouldAssert(AssertionLevel.Normal)) { var oldText = this.scriptSnapshot; var newText = scriptSnapshot; - TypeScript.Debug.assert((oldText.getLength() - textChangeRange.span().length() + textChangeRange.newLength()) === newText.getLength()); + Debug.assert((oldText.getLength() - textChangeRange.span().length() + textChangeRange.newLength()) === newText.getLength()); if (Debug.shouldAssert(AssertionLevel.VeryAggressive)) { var oldTextPrefix = oldText.getText(0, textChangeRange.span().start()); var newTextPrefix = newText.getText(0, textChangeRange.span().start()); - TypeScript.Debug.assert(oldTextPrefix === newTextPrefix); + Debug.assert(oldTextPrefix === newTextPrefix); var oldTextSuffix = oldText.getText(textChangeRange.span().end(), oldText.getLength()); var newTextSuffix = newText.getText(textChangeRange.newSpan().end(), newText.getLength()); - TypeScript.Debug.assert(oldTextSuffix === newTextSuffix); + Debug.assert(oldTextSuffix === newTextSuffix); } } return SourceFileObject.createSourceFileObject(this.filename, scriptSnapshot, this.languageVersion, version, isOpen); } - public static createSourceFileObject(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, languageVersion: ScriptTarget, version: string, isOpen: boolean) { + public static createSourceFileObject(filename: string, scriptSnapshot: IScriptSnapshot, languageVersion: ScriptTarget, version: string, isOpen: boolean) { var newSourceFile = createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, version, isOpen); newSourceFile.scriptSnapshot = scriptSnapshot; return newSourceFile; @@ -801,7 +851,7 @@ module ts { getScriptFileNames(): string[]; getScriptVersion(fileName: string): string; getScriptIsOpen(fileName: string): boolean; - getScriptSnapshot(fileName: string): TypeScript.IScriptSnapshot; + getScriptSnapshot(fileName: string): IScriptSnapshot; getLocalizedDiagnosticMessages(): any; getCancellationToken(): CancellationToken; getCurrentDirectory(): string; @@ -819,17 +869,17 @@ module ts { getSemanticDiagnostics(fileName: string): Diagnostic[]; getCompilerOptionsDiagnostics(): Diagnostic[]; - getSyntacticClassifications(fileName: string, span: TypeScript.TextSpan): ClassifiedSpan[]; - getSemanticClassifications(fileName: string, span: TypeScript.TextSpan): ClassifiedSpan[]; + getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; + getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; getCompletionsAtPosition(fileName: string, position: number, isMemberCompletion: boolean): CompletionInfo; getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails; getQuickInfoAtPosition(fileName: string, position: number): QuickInfo; - getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TypeScript.TextSpan; + getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan; - getBreakpointStatementAtPosition(fileName: string, position: number): TypeScript.TextSpan; + getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan; getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems; @@ -849,7 +899,7 @@ module ts { getOutliningSpans(fileName: string): OutliningSpan[]; getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[]; - getBraceMatchingAtPosition(fileName: string, position: number): TypeScript.TextSpan[]; + getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[]; getIndentationAtPosition(fileName: string, position: number, options: EditorOptions): number; getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[]; @@ -858,8 +908,6 @@ module ts { getEmitOutput(fileName: string): EmitOutput; - //getSyntaxTree(fileName: string): TypeScript.SyntaxTree; - dispose(): void; } @@ -899,7 +947,7 @@ module ts { } export interface ClassifiedSpan { - textSpan: TypeScript.TextSpan; + textSpan: TextSpan; classificationType: string; // ClassificationTypeNames } @@ -907,7 +955,7 @@ module ts { text: string; kind: string; kindModifiers: string; - spans: TypeScript.TextSpan[]; + spans: TextSpan[]; childItems: NavigationBarItem[]; indent: number; bolded: boolean; @@ -926,17 +974,17 @@ module ts { } export class TextChange { - span: TypeScript.TextSpan; + span: TextSpan; newText: string; } export interface RenameLocation { - textSpan: TypeScript.TextSpan; + textSpan: TextSpan; fileName: string; } export interface ReferenceEntry { - textSpan: TypeScript.TextSpan; + textSpan: TextSpan; fileName: string; isWriteAccess: boolean; } @@ -947,7 +995,7 @@ module ts { kindModifiers: string; matchKind: string; fileName: string; - textSpan: TypeScript.TextSpan; + textSpan: TextSpan; containerName: string; containerKind: string; } @@ -972,7 +1020,7 @@ module ts { export interface DefinitionInfo { fileName: string; - textSpan: TypeScript.TextSpan; + textSpan: TextSpan; kind: string; name: string; containerKind: string; @@ -1012,7 +1060,7 @@ module ts { export interface QuickInfo { kind: string; kindModifiers: string; - textSpan: TypeScript.TextSpan; + textSpan: TextSpan; displayParts: SymbolDisplayPart[]; documentation: SymbolDisplayPart[]; } @@ -1024,7 +1072,7 @@ module ts { fullDisplayName: string; kind: string; kindModifiers: string; - triggerSpan: TypeScript.TextSpan; + triggerSpan: TextSpan; } export interface SignatureHelpParameter { @@ -1055,7 +1103,7 @@ module ts { */ export interface SignatureHelpItems { items: SignatureHelpItem[]; - applicableSpan: TypeScript.TextSpan; + applicableSpan: TextSpan; selectedItemIndex: number; argumentIndex: number; argumentCount: number; @@ -1134,7 +1182,7 @@ module ts { acquireDocument( filename: string, compilationSettings: CompilerOptions, - scriptSnapshot: TypeScript.IScriptSnapshot, + scriptSnapshot: IScriptSnapshot, version: string, isOpen: boolean): SourceFile; @@ -1142,10 +1190,10 @@ module ts { sourceFile: SourceFile, filename: string, compilationSettings: CompilerOptions, - scriptSnapshot: TypeScript.IScriptSnapshot, + scriptSnapshot: IScriptSnapshot, version: string, isOpen: boolean, - textChangeRange: TypeScript.TextChangeRange + textChangeRange: TextChangeRange ): SourceFile; releaseDocument(filename: string, compilationSettings: CompilerOptions): void @@ -1263,10 +1311,6 @@ module ts { prefix = 3 } - interface IncrementalParse { - (oldSyntaxTree: TypeScript.SyntaxTree, textChangeRange: TypeScript.TextChangeRange, newText: TypeScript.ISimpleText): TypeScript.SyntaxTree - } - /// Language Service interface CompletionSession { @@ -1289,7 +1333,7 @@ module ts { filename: string; version: string; isOpen: boolean; - sourceText?: TypeScript.IScriptSnapshot; + sourceText?: IScriptSnapshot; } interface DocumentRegistryEntry { @@ -1579,7 +1623,7 @@ module ts { return this.getEntry(filename).isOpen; } - public getScriptSnapshot(filename: string): TypeScript.IScriptSnapshot { + public getScriptSnapshot(filename: string): IScriptSnapshot { var file = this.getEntry(filename); if (!file.sourceText) { file.sourceText = this.host.getScriptSnapshot(file.filename); @@ -1587,10 +1631,10 @@ module ts { return file.sourceText; } - public getChangeRange(filename: string, lastKnownVersion: string, oldScriptSnapshot: TypeScript.IScriptSnapshot): TypeScript.TextChangeRange { + public getChangeRange(filename: string, lastKnownVersion: string, oldScriptSnapshot: IScriptSnapshot): TextChangeRange { var currentVersion = this.getVersion(filename); if (lastKnownVersion === currentVersion) { - return TypeScript.TextChangeRange.unchanged; // "No changes" + return TextChangeRange.unchanged; // "No changes" } var scriptSnapshot = this.getScriptSnapshot(filename); @@ -1606,7 +1650,6 @@ module ts { private currentFilename: string = ""; private currentFileVersion: string = null; private currentSourceFile: SourceFile = null; - private currentFileSyntaxTree: TypeScript.SyntaxTree = null; constructor(private host: LanguageServiceHost) { this.hostCache = new HostCache(host); @@ -1614,20 +1657,15 @@ module ts { private initialize(filename: string) { // ensure that both source file and syntax tree are either initialized or not initialized - Debug.assert(!!this.currentFileSyntaxTree === !!this.currentSourceFile); var start = new Date().getTime(); this.hostCache = new HostCache(this.host); this.host.log("SyntaxTreeCache.Initialize: new HostCache: " + (new Date().getTime() - start)); var version = this.hostCache.getVersion(filename); - var syntaxTree: TypeScript.SyntaxTree = null; var sourceFile: SourceFile; - if (this.currentFileSyntaxTree === null || this.currentFilename !== filename) { + if (this.currentFilename !== filename) { var scriptSnapshot = this.hostCache.getScriptSnapshot(filename); - var start = new Date().getTime(); - syntaxTree = this.createSyntaxTree(filename, scriptSnapshot); - this.host.log("SyntaxTreeCache.Initialize: createSyntaxTree: " + (new Date().getTime() - start)); var start = new Date().getTime(); sourceFile = createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true); @@ -1640,11 +1678,6 @@ module ts { else if (this.currentFileVersion !== version) { var scriptSnapshot = this.hostCache.getScriptSnapshot(filename); - var start = new Date().getTime(); - syntaxTree = this.updateSyntaxTree(filename, scriptSnapshot, - this.currentSourceFile.getScriptSnapshot(), this.currentFileSyntaxTree, this.currentFileVersion); - this.host.log("SyntaxTreeCache.Initialize: updateSyntaxTree: " + (new Date().getTime() - start)); - var editRange = this.hostCache.getChangeRange(filename, this.currentFileVersion, this.currentSourceFile.getScriptSnapshot()); var start = new Date().getTime(); @@ -1658,12 +1691,10 @@ module ts { this.host.log("SyntaxTreeCache.Initialize: fixupParentRefs : " + (new Date().getTime() - start)); } - if (syntaxTree !== null) { - Debug.assert(sourceFile !== undefined); + if (sourceFile) { // All done, ensure state is up to date this.currentFileVersion = version; this.currentFilename = filename; - this.currentFileSyntaxTree = syntaxTree; this.currentSourceFile = sourceFile; } @@ -1684,115 +1715,17 @@ module ts { } } - public getCurrentFileSyntaxTree(filename: string): TypeScript.SyntaxTree { - this.initialize(filename); - return this.currentFileSyntaxTree; - } - public getCurrentSourceFile(filename: string): SourceFile { this.initialize(filename); return this.currentSourceFile; } - public getCurrentScriptSnapshot(filename: string): TypeScript.IScriptSnapshot { - // update currentFileScriptSnapshot as a part of 'getCurrentFileSyntaxTree' call - this.getCurrentFileSyntaxTree(filename); + public getCurrentScriptSnapshot(filename: string): IScriptSnapshot { return this.getCurrentSourceFile(filename).getScriptSnapshot(); } - - private createSyntaxTree(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot): TypeScript.SyntaxTree { - var text = TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot); - - // For the purposes of features that use this syntax tree, we can just use the default - // compilation settings. The features only use the syntax (and not the diagnostics), - // and the syntax isn't affected by the compilation settings. - var syntaxTree = TypeScript.Parser.parse(filename, text, getDefaultCompilerOptions().target, TypeScript.isDTSFile(filename)); - - return syntaxTree; - } - - 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); - - // The host considers the entire buffer changed. So parse a completely new tree. - if (editRange === null) { - return this.createSyntaxTree(filename, scriptSnapshot); - } - - var nextSyntaxTree = TypeScript.IncrementalParser.parse( - previousSyntaxTree, editRange, TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot)); - - this.ensureInvariants(filename, editRange, nextSyntaxTree, previousScriptSnapshot, scriptSnapshot); - - return nextSyntaxTree; - } - - private ensureInvariants(filename: string, editRange: TypeScript.TextChangeRange, incrementalTree: TypeScript.SyntaxTree, oldScriptSnapshot: TypeScript.IScriptSnapshot, newScriptSnapshot: TypeScript.IScriptSnapshot) { - // First, verify that the edit range and the script snapshots make sense. - - // If this fires, then the edit range is completely bogus. Somehow the lengths of the - // old snapshot, the change range and the new snapshot aren't in sync. This is very - // bad. - var expectedNewLength = oldScriptSnapshot.getLength() - editRange.span().length() + editRange.newLength(); - var actualNewLength = newScriptSnapshot.getLength(); - - function provideMoreDebugInfo() { - - var debugInformation = ["expected length:", expectedNewLength, "and actual length:", actualNewLength, "are not equal\r\n"]; - - var oldSpan = editRange.span(); - - function prettyPrintString(s: string): string { - return '"' + s.replace(/\r/g, '\\r').replace(/\n/g, '\\n') + '"'; - } - - debugInformation.push('Edit range (old text) (start: ' + oldSpan.start() + ', end: ' + oldSpan.end() + ') \r\n'); - debugInformation.push('Old text edit range contents: ' + prettyPrintString(oldScriptSnapshot.getText(oldSpan.start(), oldSpan.end()))); - - var newSpan = editRange.newSpan(); - - debugInformation.push('Edit range (new text) (start: ' + newSpan.start() + ', end: ' + newSpan.end() + ') \r\n'); - debugInformation.push('New text edit range contents: ' + prettyPrintString(newScriptSnapshot.getText(newSpan.start(), newSpan.end()))); - - return debugInformation.join(' '); - } - - Debug.assert( - expectedNewLength === actualNewLength, - "Expected length is different from actual!", - provideMoreDebugInfo); - - if (Debug.shouldAssert(AssertionLevel.VeryAggressive)) { - // If this fires, the text change range is bogus. It says the change starts at point - // 'X', but we can see a text difference *before* that point. - var oldPrefixText = oldScriptSnapshot.getText(0, editRange.span().start()); - var newPrefixText = newScriptSnapshot.getText(0, editRange.span().start()); - Debug.assert(oldPrefixText === newPrefixText, 'Expected equal prefix texts!'); - - // If this fires, the text change range is bogus. It says the change goes only up to - // point 'X', but we can see a text difference *after* that point. - var oldSuffixText = oldScriptSnapshot.getText(editRange.span().end(), oldScriptSnapshot.getLength()); - var newSuffixText = newScriptSnapshot.getText(editRange.newSpan().end(), newScriptSnapshot.getLength()); - Debug.assert(oldSuffixText === newSuffixText, 'Expected equal suffix texts!'); - - // Ok, text change range and script snapshots look ok. Let's verify that our - // incremental parsing worked properly. - //var normalTree = this.createSyntaxTree(filename, newScriptSnapshot); - //Debug.assert(normalTree.structuralEquals(incrementalTree), 'Expected equal incremental and normal trees'); - - // Ok, the trees looked good. So at least our incremental parser agrees with the - // normal parser. Now, verify that the incremental tree matches the contents of the - // script snapshot. - var incrementalTreeText = TypeScript.fullText(incrementalTree.sourceUnit()); - var actualSnapshotText = newScriptSnapshot.getText(0, newScriptSnapshot.getLength()); - Debug.assert(incrementalTreeText === actualSnapshotText, 'Expected full texts to be equal'); - } - } } - function createSourceFileFromScriptSnapshot(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, settings: CompilerOptions, version: string, isOpen: boolean) { + function createSourceFileFromScriptSnapshot(filename: string, scriptSnapshot: IScriptSnapshot, settings: CompilerOptions, version: string, isOpen: boolean) { return SourceFileObject.createSourceFileObject(filename, scriptSnapshot, settings.target, version, isOpen); } @@ -1836,7 +1769,7 @@ module ts { function acquireDocument( filename: string, compilationSettings: CompilerOptions, - scriptSnapshot: TypeScript.IScriptSnapshot, + scriptSnapshot: IScriptSnapshot, version: string, isOpen: boolean): SourceFile { @@ -1860,10 +1793,10 @@ module ts { sourceFile: SourceFile, filename: string, compilationSettings: CompilerOptions, - scriptSnapshot: TypeScript.IScriptSnapshot, + scriptSnapshot: IScriptSnapshot, version: string, isOpen: boolean, - textChangeRange: TypeScript.TextChangeRange + textChangeRange: TextChangeRange ): SourceFile { var bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ false); @@ -2137,7 +2070,7 @@ module ts { export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry): LanguageService { var syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); - var ruleProvider: ts.formatting.RulesProvider; + var ruleProvider: formatting.RulesProvider; var hostCache: HostCache; // A cache of all the information about the files on the host side. var program: Program; @@ -2171,7 +2104,7 @@ module ts { function getRuleProvider(options: FormatCodeOptions) { // Ensure rules are initialized and up to date wrt to formatting options if (!ruleProvider) { - ruleProvider = new ts.formatting.RulesProvider(host); + ruleProvider = new formatting.RulesProvider(host); } ruleProvider.ensureUpToDate(options); @@ -2288,7 +2221,7 @@ module ts { // file was closed, then we always want to re-parse. This is so our tree doesn't keep // the old buffer alive that represented the file on disk (as the host has moved to a // new text buffer). - var textChangeRange: TypeScript.TextChangeRange = null; + var textChangeRange: TextChangeRange = null; if (sourceFile.isOpen && isOpen) { textChangeRange = hostCache.getChangeRange(filename, sourceFile.version, sourceFile.getScriptSnapshot()); } @@ -3295,7 +3228,7 @@ module ts { return { kind: ScriptElementKind.unknown, kindModifiers: ScriptElementKindModifier.none, - textSpan: new TypeScript.TextSpan(node.getStart(), node.getWidth()), + textSpan: new TextSpan(node.getStart(), node.getWidth()), displayParts: typeToDisplayParts(typeInfoResolver, type, getContainerNode(node)), documentation: type.symbol ? type.symbol.getDocumentationComment() : undefined }; @@ -3309,7 +3242,7 @@ module ts { return { kind: displayPartsDocumentationsAndKind.symbolKind, kindModifiers: getSymbolModifiers(symbol), - textSpan: new TypeScript.TextSpan(node.getStart(), node.getWidth()), + textSpan: new TextSpan(node.getStart(), node.getWidth()), displayParts: displayPartsDocumentationsAndKind.displayParts, documentation: displayPartsDocumentationsAndKind.documentation }; @@ -3320,7 +3253,7 @@ module ts { function getDefinitionInfo(node: Node, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo { return { fileName: node.getSourceFile().filename, - textSpan: TypeScript.TextSpan.fromBounds(node.getStart(), node.getEnd()), + textSpan: TextSpan.fromBounds(node.getStart(), node.getEnd()), kind: symbolKind, name: symbolName, containerKind: undefined, @@ -3398,7 +3331,7 @@ module ts { if (program.getSourceFile(targetFilename)) { return [{ fileName: targetFilename, - textSpan: TypeScript.TextSpan.fromBounds(0, 0), + textSpan: TextSpan.fromBounds(0, 0), kind: ScriptElementKind.scriptElement, name: comment.filename, containerName: undefined, @@ -3584,7 +3517,7 @@ module ts { if (shouldHighlightNextKeyword) { result.push({ fileName: filename, - textSpan: TypeScript.TextSpan.fromBounds(elseKeyword.getStart(), ifKeyword.end), + textSpan: TextSpan.fromBounds(elseKeyword.getStart(), ifKeyword.end), isWriteAccess: false }); i++; // skip the next keyword @@ -4170,7 +4103,7 @@ module ts { (findInComments && isInComment(position))) { result.push({ fileName: sourceFile.filename, - textSpan: new TypeScript.TextSpan(position, searchText.length), + textSpan: new TextSpan(position, searchText.length), isWriteAccess: false }); } @@ -4539,7 +4472,7 @@ module ts { return { fileName: node.getSourceFile().filename, - textSpan: TypeScript.TextSpan.fromBounds(start, end), + textSpan: TextSpan.fromBounds(start, end), isWriteAccess: isWriteAccess(node) }; } @@ -4595,7 +4528,7 @@ module ts { kindModifiers: getNodeModifiers(declaration), matchKind: MatchKind[matchKind], fileName: filename, - textSpan: TypeScript.TextSpan.fromBounds(declaration.getStart(), declaration.getEnd()), + textSpan: TextSpan.fromBounds(declaration.getStart(), declaration.getEnd()), // TODO(jfreeman): What should be the containerName when the container has a computed name? containerName: container.name ? (container.name).text : "", containerKind: container.name ? getNodeKind(container) : "" @@ -4900,18 +4833,13 @@ module ts { } /// Syntactic features - function getSyntaxTree(filename: string): TypeScript.SyntaxTree { - filename = normalizeSlashes(filename); - return syntaxTreeCache.getCurrentFileSyntaxTree(filename); - } - function getCurrentSourceFile(filename: string): SourceFile { filename = normalizeSlashes(filename); var currentSourceFile = syntaxTreeCache.getCurrentSourceFile(filename); return currentSourceFile; } - function getNameOrDottedNameSpan(filename: string, startPos: number, endPos: number): TypeScript.TextSpan { + function getNameOrDottedNameSpan(filename: string, startPos: number, endPos: number): TextSpan { filename = ts.normalizeSlashes(filename); // Get node at the location var node = getTouchingPropertyName(getCurrentSourceFile(filename), startPos); @@ -4963,7 +4891,7 @@ module ts { } } - return TypeScript.TextSpan.fromBounds(nodeForStartPos.getStart(), node.getEnd()); + return TextSpan.fromBounds(nodeForStartPos.getStart(), node.getEnd()); } function getBreakpointStatementAtPosition(filename: string, position: number) { @@ -4978,7 +4906,7 @@ module ts { return NavigationBar.getNavigationBarItems(getCurrentSourceFile(filename)); } - function getSemanticClassifications(fileName: string, span: TypeScript.TextSpan): ClassifiedSpan[] { + function getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] { synchronizeHostData(); fileName = normalizeSlashes(fileName); @@ -5037,7 +4965,7 @@ module ts { var type = classifySymbol(symbol, getMeaningFromLocation(node)); if (type) { result.push({ - textSpan: new TypeScript.TextSpan(node.getStart(), node.getWidth()), + textSpan: new TextSpan(node.getStart(), node.getWidth()), classificationType: type }); } @@ -5049,7 +4977,7 @@ module ts { } } - function getSyntacticClassifications(fileName: string, span: TypeScript.TextSpan): ClassifiedSpan[] { + function getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] { // doesn't use compiler - no need to synchronize with host fileName = normalizeSlashes(fileName); var sourceFile = getCurrentSourceFile(fileName); @@ -5063,7 +4991,7 @@ module ts { var width = comment.end - comment.pos; if (span.intersectsWith(comment.pos, width)) { result.push({ - textSpan: new TypeScript.TextSpan(comment.pos, width), + textSpan: new TextSpan(comment.pos, width), classificationType: ClassificationTypeNames.comment }); } @@ -5076,7 +5004,7 @@ module ts { var type = classifyTokenType(token); if (type) { result.push({ - textSpan: new TypeScript.TextSpan(token.getStart(), token.getWidth()), + textSpan: new TextSpan(token.getStart(), token.getWidth()), classificationType: type }); } @@ -5188,7 +5116,7 @@ module ts { function getBraceMatchingAtPosition(filename: string, position: number) { var sourceFile = getCurrentSourceFile(filename); - var result: TypeScript.TextSpan[] = []; + var result: TextSpan[] = []; var token = getTouchingToken(sourceFile, position); @@ -5200,12 +5128,12 @@ module ts { var parentElement = token.parent; var childNodes = parentElement.getChildren(sourceFile); - for (var i = 0, n = childNodes.length; i < n; i++) { + for (var i = 0, n = childNodes.length; i < n; i++) {33 var current = childNodes[i]; if (current.kind === matchKind) { - var range1 = new TypeScript.TextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); - var range2 = new TypeScript.TextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); + var range1 = new TextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); + var range2 = new TextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); // We want to order the braces when we return the result. if (range1.start() < range2.start()) { @@ -5444,9 +5372,9 @@ module ts { } 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); + return (char >= CharacterCodes.a && char <= CharacterCodes.z) || + (char >= CharacterCodes.A && char <= CharacterCodes.Z) || + (char >= CharacterCodes._0 && char <= CharacterCodes._9); } } @@ -5469,7 +5397,7 @@ module ts { if (kind) { return getRenameInfo(symbol.name, typeInfoResolver.getFullyQualifiedName(symbol), kind, getSymbolModifiers(symbol), - new TypeScript.TextSpan(node.getStart(), node.getWidth())); + new TextSpan(node.getStart(), node.getWidth())); } } } @@ -5488,7 +5416,7 @@ module ts { }; } - function getRenameInfo(displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, triggerSpan: TypeScript.TextSpan): RenameInfo { + function getRenameInfo(displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, triggerSpan: TextSpan): RenameInfo { return { canRename: true, localizedErrorMessage: undefined, diff --git a/src/services/shims.ts b/src/services/shims.ts index 00acff3798a..38c68c067f8 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -15,8 +15,6 @@ /// -/// - var debugObjectHost = (this); module ts { @@ -176,7 +174,7 @@ module ts { } export interface CoreServicesShim extends Shim { - getPreProcessedFileInfo(fileName: string, sourceText: TypeScript.IScriptSnapshot): string; + getPreProcessedFileInfo(fileName: string, sourceText: IScriptSnapshot): string; getDefaultCompilationSettings(): string; } @@ -309,7 +307,7 @@ module ts { logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message); } - class ScriptSnapshotShimAdapter implements TypeScript.IScriptSnapshot { + class ScriptSnapshotShimAdapter implements IScriptSnapshot { private lineStartPositions: number[] = null; constructor(private scriptSnapshotShim: ScriptSnapshotShim) { @@ -331,7 +329,7 @@ module ts { return this.lineStartPositions; } - public getChangeRange(oldSnapshot: TypeScript.IScriptSnapshot): TypeScript.TextChangeRange { + public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange { var oldSnapshotShim = oldSnapshot; var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim); if (encoded == null) { @@ -339,8 +337,8 @@ module ts { } 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); + return new TextChangeRange( + new TextSpan(decoded.span.start, decoded.span.length), decoded.newLength); } } @@ -368,7 +366,7 @@ module ts { return JSON.parse(encoded); } - public getScriptSnapshot(fileName: string): TypeScript.IScriptSnapshot { + public getScriptSnapshot(fileName: string): IScriptSnapshot { return new ScriptSnapshotShimAdapter(this.shimHost.getScriptSnapshot(fileName)); } @@ -521,7 +519,7 @@ module ts { return this.forwardJSONCall( "getSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", () => { - var classifications = this.languageService.getSyntacticClassifications(fileName, new TypeScript.TextSpan(start, length)); + var classifications = this.languageService.getSyntacticClassifications(fileName, new TextSpan(start, length)); return classifications; }); } @@ -530,7 +528,7 @@ module ts { return this.forwardJSONCall( "getSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", () => { - var classifications = this.languageService.getSemanticClassifications(fileName, new TypeScript.TextSpan(start, length)); + var classifications = this.languageService.getSemanticClassifications(fileName, new TextSpan(start, length)); return classifications; }); } @@ -845,7 +843,7 @@ module ts { return forwardJSONCall(this.logger, actionDescription, action); } - public getPreProcessedFileInfo(fileName: string, sourceTextSnapshot: TypeScript.IScriptSnapshot): string { + public getPreProcessedFileInfo(fileName: string, sourceTextSnapshot: IScriptSnapshot): string { return this.forwardJSONCall( "getPreProcessedFileInfo('" + fileName + "')", () => { @@ -938,7 +936,7 @@ module ts { } } - throw TypeScript.Errors.invalidOperation(); + throw new Error("Invalid operation"); } } } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 41f64c1b8db..a4580582ed8 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -353,7 +353,7 @@ module ts.SignatureHelp { // but not including parentheses) var applicableSpanStart = argumentListOrTypeArgumentList.getFullStart(); var applicableSpanEnd = skipTrivia(sourceFile.text, argumentListOrTypeArgumentList.end, /*stopAfterLineBreak*/ false); - var applicableSpan = new TypeScript.TextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); + var applicableSpan = new TextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); // The listItemIndex we got back includes commas. Our goal is to return the index of the proper // item (not including commas). Here are some examples: diff --git a/src/services/syntax/parser.ts b/src/services/syntax/parser.ts index 8f8bae4e549..80c813ca162 100644 --- a/src/services/syntax/parser.ts +++ b/src/services/syntax/parser.ts @@ -1373,7 +1373,8 @@ module TypeScript.Parser { function parseFunctionDeclarationWorker(modifiers: ISyntaxToken[], functionKeyword: ISyntaxToken, asteriskToken: ISyntaxToken): FunctionDeclarationSyntax { // GeneratorDeclaration[Yield, Default] : - // function * BindingIdentifier[?Yield](FormalParameters[Yield, GeneratorParameter]) { GeneratorBody[Yield] } + // function * BindingIdentifier[?Yield](FormalParameters[Yield, GeneratorParameter]) { GeneratorBody[Yield] } + var isGenerator = asteriskToken !== undefined; return new FunctionDeclarationSyntax(parseNodeData, modifiers, @@ -2167,14 +2168,9 @@ module TypeScript.Parser { case SyntaxKind.SlashToken: case SyntaxKind.SlashEqualsToken: - // Note: if we see a / or /= token then we always consider this an expression. Why? - // Well, either that / or /= is actually a regular expression, in which case we're - // definitely an expression. Or, it's actually a divide. In which case, we *still* - // want to think of ourself as an expression. "But wait", you say. '/' doesn't - // start an expression. That's true. BUt like the above check for =>, for error - // tolerance, we will consider ourselves in an expression. We'll then parse out an - // missing identifier and then will consume the / token naturally as a binary - // expression. + // Note: if we see a / or /= token then we always consider this an expression. + // The / or /= will actually be the start of a regex that we will contextually + // rescan. // Simple epxressions. case SyntaxKind.SuperKeyword: @@ -2976,15 +2972,9 @@ module TypeScript.Parser { case SyntaxKind.SlashToken: case SyntaxKind.SlashEqualsToken: - // If we see a standalone / or /= and we're expecting a term, then try to reparse + // If we see a standalone / or /= and we're expecting an expression, then reparse // it as a regular expression. - var result = tryReparseDivideAsRegularExpression(); - - // If we get a result, then use it. Otherwise, create a missing identifier so - // that parsing can continue. Note: we do this even if 'force' is false. That's - // because we *do* want to consider a standalone / as an expression that should be - // returned from tryParseExpression even when 'force' is set to false. - return result || eatIdentifierToken(DiagnosticCode.Expression_expected); + return reparseDivideAsRegularExpression(); } if (!force) { @@ -2995,7 +2985,7 @@ module TypeScript.Parser { return eatIdentifierToken(DiagnosticCode.Expression_expected); } - function tryReparseDivideAsRegularExpression(): IPrimaryExpressionSyntax { + function reparseDivideAsRegularExpression(): IPrimaryExpressionSyntax { // If we see a / or /= token, then that may actually be the start of a regex in certain // contexts. @@ -3012,18 +3002,9 @@ module TypeScript.Parser { // Debug.assert(SyntaxFacts.isAnyDivideOrRegularExpressionToken(currentToken.kind)); var tokenKind = currentToken.kind; - if (tokenKind === SyntaxKind.SlashToken || tokenKind === SyntaxKind.SlashEqualsToken) { - // Still came back as a / or /=. This is not a regular expression literal. - return undefined; - } - else if (tokenKind === SyntaxKind.RegularExpressionLiteral) { - return consumeToken(currentToken); - } - else { - // Something *very* wrong happened. This is an internal parser fault that we need - // to figure out and fix. - throw Errors.invalidOperation(); - } + Debug.assert(tokenKind === SyntaxKind.RegularExpressionLiteral); + + return consumeToken(currentToken); } function parseTypeOfExpression(typeOfKeyword: ISyntaxToken): TypeOfExpressionSyntax { diff --git a/src/services/syntax/scanner.ts b/src/services/syntax/scanner.ts index 54f05890e3e..17b127eb6a9 100644 --- a/src/services/syntax/scanner.ts +++ b/src/services/syntax/scanner.ts @@ -281,7 +281,7 @@ module TypeScript.Scanner { LargeScannerToken.prototype.childCount = 0; export interface DiagnosticCallback { - (position: number, width: number, key: string, arguments: any[]): void; + (position: number, width: number, key: string, arguments?: any[]): void; } interface TokenInfo { @@ -1008,7 +1008,7 @@ module TypeScript.Scanner { while (true) { if (index === end) { // Hit the end of the file. - reportDiagnostic(end, 0, DiagnosticCode._0_expected, ["`"]); + reportDiagnostic(end, 0, DiagnosticCode.Unterminated_template_literal); break; } @@ -1144,10 +1144,7 @@ module TypeScript.Scanner { // term, and it sees one of these then it may restart us asking specifically if we could // scan out a regex. if (allowContextualToken) { - var result = tryScanRegularExpressionToken(); - if (result !== SyntaxKind.None) { - return result; - } + return scanRegularExpressionToken(); } if (str.charCodeAt(index) === CharacterCodes.equals) { @@ -1159,7 +1156,7 @@ module TypeScript.Scanner { } } - function tryScanRegularExpressionToken(): SyntaxKind { + function scanRegularExpressionToken(): SyntaxKind { var startIndex = index; var inEscape = false; @@ -1168,8 +1165,9 @@ module TypeScript.Scanner { var ch = str.charCodeAt(index); if (isNaN(ch) || isNewLineCharacter(ch)) { - index = startIndex; - return SyntaxKind.None; + // Hit the end of line, or end of the file. This is not a legal regex. + reportDiagnostic(index, 0, DiagnosticCode.Unterminated_regular_expression_literal); + break; } index++; @@ -1193,7 +1191,7 @@ module TypeScript.Scanner { continue; case CharacterCodes.closeBracket: - // If we ever hit a cloe bracket then we're now no longer in a character + // If we ever hit a close bracket then we're now no longer in a character // class. If we weren't in a character class to begin with, then this has // no effect. inCharacterClass = false; @@ -1219,7 +1217,7 @@ module TypeScript.Scanner { // TODO: The grammar says any identifier part is allowed here. Do we need to support // \u identifiers here? The existing typescript parser does not. - while (isIdentifierPartCharacter[str.charCodeAt(index)]) { + while (index < end && isIdentifierPartCharacter[str.charCodeAt(index)]) { index++; } @@ -1322,7 +1320,7 @@ module TypeScript.Scanner { break; } else if (isNaN(ch) || isNewLineCharacter(ch)) { - reportDiagnostic(Math.min(index, end), 1, DiagnosticCode.Missing_close_quote_character, undefined); + reportDiagnostic(index, 0, DiagnosticCode.Unterminated_string_literal); break; } else { diff --git a/src/services/text.ts b/src/services/text.ts new file mode 100644 index 00000000000..fd768785dea --- /dev/null +++ b/src/services/text.ts @@ -0,0 +1,296 @@ +module ts { + export class TextSpan { + private _start: number; + private _length: number; + + /** + * Creates a TextSpan instance beginning with the position Start and having the Length + * specified with length. + */ + constructor(start: number, length: number) { + Debug.assert(start >= 0, "start"); + Debug.assert(length >= 0, "length"); + + this._start = start; + this._length = length; + } + + public toJSON(key: any): any { + return { start: this._start, length: this._length }; + } + + public start(): number { + return this._start; + } + + public length(): number { + return this._length; + } + + public end(): number { + return this._start + this._length; + } + + public isEmpty(): boolean { + return this._length === 0; + } + + /** + * Determines whether the position lies within the span. Returns true if the position is greater than or equal to Start and strictly less + * than End, otherwise false. + * @param position The position to check. + */ + public containsPosition(position: number): boolean { + return position >= this._start && position < this.end(); + } + + /** + * Determines whether span falls completely within this span. Returns true if the specified span falls completely within this span, otherwise false. + * @param span The span to check. + */ + public containsTextSpan(span: TextSpan): boolean { + return span._start >= this._start && span.end() <= this.end(); + } + + /** + * Determines whether the given span overlaps this span. Two spans are considered to overlap + * if they have positions in common and neither is empty. Empty spans do not overlap with any + * other span. Returns true if the spans overlap, false otherwise. + * @param span The span to check. + */ + public overlapsWith(span: TextSpan): boolean { + var overlapStart = Math.max(this._start, span._start); + var overlapEnd = Math.min(this.end(), span.end()); + + return overlapStart < overlapEnd; + } + + /** + * Returns the overlap with the given span, or undefined if there is no overlap. + * @param span The span to check. + */ + public overlap(span: TextSpan): TextSpan { + var overlapStart = Math.max(this._start, span._start); + var overlapEnd = Math.min(this.end(), span.end()); + + if (overlapStart < overlapEnd) { + return TextSpan.fromBounds(overlapStart, overlapEnd); + } + + return undefined; + } + + /** + * Determines whether span intersects this span. Two spans are considered to + * intersect if they have positions in common or the end of one span + * coincides with the start of the other span. Returns true if the spans intersect, false otherwise. + * @param The span to check. + */ + public intersectsWithTextSpan(span: TextSpan): boolean { + return span._start <= this.end() && span.end() >= this._start; + } + + public intersectsWith(start: number, length: number): boolean { + var end = start + length; + return start <= this.end() && end >= this._start; + } + + /** + * Determines whether the given position intersects this span. + * A position is considered to intersect if it is between the start and + * end positions (inclusive) of this span. Returns true if the position intersects, false otherwise. + * @param position The position to check. + */ + public intersectsWithPosition(position: number): boolean { + return position <= this.end() && position >= this._start; + } + + /** + * Returns the intersection with the given span, or undefined if there is no intersection. + * @param span The span to check. + */ + public intersection(span: TextSpan): TextSpan { + var intersectStart = Math.max(this._start, span._start); + var intersectEnd = Math.min(this.end(), span.end()); + + if (intersectStart <= intersectEnd) { + return TextSpan.fromBounds(intersectStart, intersectEnd); + } + + return undefined; + } + + /** + * Creates a new TextSpan from the given start and end positions + * as opposed to a position and length. + */ + public static fromBounds(start: number, end: number): TextSpan { + Debug.assert(start >= 0); + Debug.assert(end - start >= 0); + return new TextSpan(start, end - start); + } + } + + export class TextChangeRange { + public static unchanged = new TextChangeRange(new TextSpan(0, 0), 0); + + private _span: TextSpan; + private _newLength: number; + + /** + * Initializes a new instance of TextChangeRange. + */ + constructor(span: TextSpan, newLength: number) { + Debug.assert(newLength >= 0, "newLength"); + + this._span = span; + this._newLength = newLength; + } + + /** + * The span of text before the edit which is being changed + */ + public span(): TextSpan { + return this._span; + } + + /** + * Width of the span after the edit. A 0 here would represent a delete + */ + public newLength(): number { + return this._newLength; + } + + public newSpan(): TextSpan { + return new TextSpan(this.span().start(), this.newLength()); + } + + public isUnchanged(): boolean { + return this.span().isEmpty() && this.newLength() === 0; + } + + /** + * Called to merge all the changes that occurred across several versions of a script snapshot + * into a single change. i.e. if a user keeps making successive edits to a script we will + * have a text change from V1 to V2, V2 to V3, ..., Vn. + * + * This function will then merge those changes into a single change range valid between V1 and + * Vn. + */ + public static collapseChangesAcrossMultipleVersions(changes: TextChangeRange[]): TextChangeRange { + if (changes.length === 0) { + return TextChangeRange.unchanged; + } + + if (changes.length === 1) { + return changes[0]; + } + + // We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd } + // as it makes things much easier to reason about. + var change0 = changes[0]; + + var oldStartN = change0.span().start(); + var oldEndN = change0.span().end(); + var newEndN = oldStartN + change0.newLength(); + + for (var i = 1; i < changes.length; i++) { + var nextChange = changes[i]; + + // Consider the following case: + // i.e. two edits. The first represents the text change range { { 10, 50 }, 30 }. i.e. The span starting + // at 10, with length 50 is reduced to length 30. The second represents the text change range { { 30, 30 }, 40 }. + // i.e. the span starting at 30 with length 30 is increased to length 40. + // + // 0 10 20 30 40 50 60 70 80 90 100 + // ------------------------------------------------------------------------------------------------------- + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ------------------------------------------------------------------------------------------------------- + // | \ + // | \ + // T2 | \ + // | \ + // | \ + // ------------------------------------------------------------------------------------------------------- + // + // Merging these turns out to not be too difficult. First, determining the new start of the change is trivial + // it's just the min of the old and new starts. i.e.: + // + // 0 10 20 30 40 50 60 70 80 90 100 + // ------------------------------------------------------------*------------------------------------------ + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ----------------------------------------$-------------------$------------------------------------------ + // . | \ + // . | \ + // T2 . | \ + // . | \ + // . | \ + // ----------------------------------------------------------------------*-------------------------------- + // + // (Note the dots represent the newly inferrred start. + // Determining the new and old end is also pretty simple. Basically it boils down to paying attention to the + // absolute positions at the asterixes, and the relative change between the dollar signs. Basically, we see + // which if the two $'s precedes the other, and we move that one forward until they line up. in this case that + // means: + // + // 0 10 20 30 40 50 60 70 80 90 100 + // --------------------------------------------------------------------------------*---------------------- + // | / + // | /---- + // T1 | /---- + // | /---- + // | /---- + // ------------------------------------------------------------$------------------------------------------ + // . | \ + // . | \ + // T2 . | \ + // . | \ + // . | \ + // ----------------------------------------------------------------------*-------------------------------- + // + // In other words (in this case), we're recognizing that the second edit happened after where the first edit + // ended with a delta of 20 characters (60 - 40). Thus, if we go back in time to where the first edit started + // that's the same as if we started at char 80 instead of 60. + // + // As it so happens, the same logic applies if the second edit precedes the first edit. In that case rahter + // than pusing the first edit forward to match the second, we'll push the second edit forward to match the + // first. + // + // In this case that means we have { oldStart: 10, oldEnd: 80, newEnd: 70 } or, in TextChangeRange + // semantics: { { start: 10, length: 70 }, newLength: 60 } + // + // The math then works out as follows. + // If we have { oldStart1, oldEnd1, newEnd1 } and { oldStart2, oldEnd2, newEnd2 } then we can compute the + // final result like so: + // + // { + // oldStart3: Min(oldStart1, oldStart2), + // oldEnd3 : Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)), + // newEnd3 : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)) + // } + + var oldStart1 = oldStartN; + var oldEnd1 = oldEndN; + var newEnd1 = newEndN; + + var oldStart2 = nextChange.span().start(); + var oldEnd2 = nextChange.span().end(); + var newEnd2 = oldStart2 + nextChange.newLength(); + + oldStartN = Math.min(oldStart1, oldStart2); + oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)); + newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)); + } + + return new TextChangeRange(TextSpan.fromBounds(oldStartN, oldEndN), /*newLength: */newEndN - oldStartN); + } + } +} \ No newline at end of file diff --git a/tests/baselines/reference/noEmitOnError.errors.txt b/tests/baselines/reference/noEmitOnError.errors.txt index 92a7151d74e..e03e5948092 100644 --- a/tests/baselines/reference/noEmitOnError.errors.txt +++ b/tests/baselines/reference/noEmitOnError.errors.txt @@ -1,9 +1,9 @@ -tests/cases/compiler/noEmitOnError.ts(2,5): error TS2322: Type 'string' is not assignable to type 'number'. - - -==== tests/cases/compiler/noEmitOnError.ts (1 errors) ==== - - var x: number = ""; - ~ -!!! error TS2322: Type 'string' is not assignable to type 'number'. +tests/cases/compiler/noEmitOnError.ts(2,5): error TS2322: Type 'string' is not assignable to type 'number'. + + +==== tests/cases/compiler/noEmitOnError.ts (1 errors) ==== + + var x: number = ""; + ~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/baselines/reference/parser645086_1.errors.txt b/tests/baselines/reference/parser645086_1.errors.txt index 71e6b31a547..d326fa23973 100644 --- a/tests/baselines/reference/parser645086_1.errors.txt +++ b/tests/baselines/reference/parser645086_1.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_1.ts(1,13): error TS1005: ',' expected. tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_1.ts(1,14): error TS1134: Variable declaration expected. -tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_1.ts(1,15): error TS1109: Expression expected. +tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_1.ts(1,15): error TS1161: Unterminated regular expression literal. ==== tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_1.ts (3 errors) ==== @@ -10,4 +10,4 @@ tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_1.ts(1,1 ~ !!! error TS1134: Variable declaration expected. -!!! error TS1109: Expression expected. \ No newline at end of file +!!! error TS1161: Unterminated regular expression literal. \ No newline at end of file diff --git a/tests/baselines/reference/parser645086_2.errors.txt b/tests/baselines/reference/parser645086_2.errors.txt index b3b5805ab8c..2d40b3c8f78 100644 --- a/tests/baselines/reference/parser645086_2.errors.txt +++ b/tests/baselines/reference/parser645086_2.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_2.ts(1,14): error TS1005: ',' expected. tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_2.ts(1,15): error TS1134: Variable declaration expected. -tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_2.ts(1,16): error TS1109: Expression expected. +tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_2.ts(1,16): error TS1161: Unterminated regular expression literal. ==== tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_2.ts (3 errors) ==== @@ -10,4 +10,4 @@ tests/cases/conformance/parser/ecmascript5/RegressionTests/parser645086_2.ts(1,1 ~ !!! error TS1134: Variable declaration expected. -!!! error TS1109: Expression expected. \ No newline at end of file +!!! error TS1161: Unterminated regular expression literal. \ No newline at end of file diff --git a/tests/baselines/reference/parserMissingToken2.errors.txt b/tests/baselines/reference/parserMissingToken2.errors.txt index abb62f83e70..31012c0865e 100644 --- a/tests/baselines/reference/parserMissingToken2.errors.txt +++ b/tests/baselines/reference/parserMissingToken2.errors.txt @@ -1,10 +1,7 @@ -tests/cases/conformance/parser/ecmascript5/MissingTokens/parserMissingToken2.ts(1,1): error TS1109: Expression expected. -tests/cases/conformance/parser/ecmascript5/MissingTokens/parserMissingToken2.ts(1,3): error TS2304: Cannot find name 'b'. +tests/cases/conformance/parser/ecmascript5/MissingTokens/parserMissingToken2.ts(1,2): error TS1161: Unterminated regular expression literal. -==== tests/cases/conformance/parser/ecmascript5/MissingTokens/parserMissingToken2.ts (2 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/MissingTokens/parserMissingToken2.ts (1 errors) ==== / b; - ~ -!!! error TS1109: Expression expected. - ~ -!!! error TS2304: Cannot find name 'b'. \ No newline at end of file + +!!! error TS1161: Unterminated regular expression literal. \ No newline at end of file diff --git a/tests/baselines/reference/parserRegularExpressionDivideAmbiguity4.errors.txt b/tests/baselines/reference/parserRegularExpressionDivideAmbiguity4.errors.txt index f53b77abbd9..7ea76fc24d1 100644 --- a/tests/baselines/reference/parserRegularExpressionDivideAmbiguity4.errors.txt +++ b/tests/baselines/reference/parserRegularExpressionDivideAmbiguity4.errors.txt @@ -1,13 +1,13 @@ -tests/cases/conformance/parser/ecmascript5/RegularExpressions/parserRegularExpressionDivideAmbiguity4.ts(1,5): error TS1109: Expression expected. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parserRegularExpressionDivideAmbiguity4.ts(1,6): error TS1161: Unterminated regular expression literal. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parserRegularExpressionDivideAmbiguity4.ts(1,17): error TS1005: ')' expected. tests/cases/conformance/parser/ecmascript5/RegularExpressions/parserRegularExpressionDivideAmbiguity4.ts(1,1): error TS2304: Cannot find name 'foo'. -tests/cases/conformance/parser/ecmascript5/RegularExpressions/parserRegularExpressionDivideAmbiguity4.ts(1,6): error TS2304: Cannot find name 'notregexp'. ==== tests/cases/conformance/parser/ecmascript5/RegularExpressions/parserRegularExpressionDivideAmbiguity4.ts (3 errors) ==== foo(/notregexp); - ~ -!!! error TS1109: Expression expected. + +!!! error TS1161: Unterminated regular expression literal. + +!!! error TS1005: ')' expected. ~~~ -!!! error TS2304: Cannot find name 'foo'. - ~~~~~~~~~ -!!! error TS2304: Cannot find name 'notregexp'. \ No newline at end of file +!!! error TS2304: Cannot find name 'foo'. \ No newline at end of file diff --git a/tests/baselines/reference/scannerStringLiterals.errors.txt b/tests/baselines/reference/scannerStringLiterals.errors.txt index 1b4ad1cd7e5..adcae9dbf93 100644 --- a/tests/baselines/reference/scannerStringLiterals.errors.txt +++ b/tests/baselines/reference/scannerStringLiterals.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/scanner/ecmascript5/scannerStringLiterals.ts(10,34): error TS1002: Unterminated string literal. -tests/cases/conformance/scanner/ecmascript5/scannerStringLiterals.ts(11,38): error TS1126: Unexpected end of text. +tests/cases/conformance/scanner/ecmascript5/scannerStringLiterals.ts(11,38): error TS1002: Unterminated string literal. ==== tests/cases/conformance/scanner/ecmascript5/scannerStringLiterals.ts (2 errors) ==== @@ -17,4 +17,4 @@ tests/cases/conformance/scanner/ecmascript5/scannerStringLiterals.ts(11,38): err !!! error TS1002: Unterminated string literal. "Should error because of end of file. -!!! error TS1126: Unexpected end of text. \ No newline at end of file +!!! error TS1002: Unterminated string literal. \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralsErrors.errors.txt b/tests/baselines/reference/stringLiteralsErrors.errors.txt index e29707d4f84..1440739ae92 100644 --- a/tests/baselines/reference/stringLiteralsErrors.errors.txt +++ b/tests/baselines/reference/stringLiteralsErrors.errors.txt @@ -14,7 +14,7 @@ tests/cases/compiler/stringLiteralsErrors.ts(22,16): error TS1125: Hexadecimal d tests/cases/compiler/stringLiteralsErrors.ts(23,17): error TS1125: Hexadecimal digit expected. tests/cases/compiler/stringLiteralsErrors.ts(24,16): error TS1125: Hexadecimal digit expected. tests/cases/compiler/stringLiteralsErrors.ts(25,15): error TS1125: Hexadecimal digit expected. -tests/cases/compiler/stringLiteralsErrors.ts(28,14): error TS1126: Unexpected end of text. +tests/cases/compiler/stringLiteralsErrors.ts(28,14): error TS1002: Unterminated string literal. ==== tests/cases/compiler/stringLiteralsErrors.ts (17 errors) ==== @@ -79,4 +79,4 @@ tests/cases/compiler/stringLiteralsErrors.ts(28,14): error TS1126: Unexpected en // End of file var es13 = " -!!! error TS1126: Unexpected end of text. \ No newline at end of file +!!! error TS1002: Unterminated string literal. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithIncompleteNoSubstitutionTemplate1.errors.txt b/tests/baselines/reference/taggedTemplatesWithIncompleteNoSubstitutionTemplate1.errors.txt index 51e362deb5d..a64f5379e47 100644 --- a/tests/baselines/reference/taggedTemplatesWithIncompleteNoSubstitutionTemplate1.errors.txt +++ b/tests/baselines/reference/taggedTemplatesWithIncompleteNoSubstitutionTemplate1.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate1.ts(6,15): error TS1126: Unexpected end of text. +tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate1.ts(6,15): error TS1160: Unterminated template literal. ==== tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate1.ts (1 errors) ==== @@ -9,4 +9,4 @@ tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate1.ts(6,1 // Incomplete call, not enough parameters. f `123qdawdrqw -!!! error TS1126: Unexpected end of text. \ No newline at end of file +!!! error TS1160: Unterminated template literal. \ No newline at end of file diff --git a/tests/baselines/reference/taggedTemplatesWithIncompleteNoSubstitutionTemplate2.errors.txt b/tests/baselines/reference/taggedTemplatesWithIncompleteNoSubstitutionTemplate2.errors.txt index 1aa00658d80..fab10f8a888 100644 --- a/tests/baselines/reference/taggedTemplatesWithIncompleteNoSubstitutionTemplate2.errors.txt +++ b/tests/baselines/reference/taggedTemplatesWithIncompleteNoSubstitutionTemplate2.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate2.ts(6,4): error TS1126: Unexpected end of text. +tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate2.ts(6,4): error TS1160: Unterminated template literal. ==== tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate2.ts (1 errors) ==== @@ -9,4 +9,4 @@ tests/cases/compiler/taggedTemplatesWithIncompleteNoSubstitutionTemplate2.ts(6,4 // Incomplete call, not enough parameters, at EOF. f ` -!!! error TS1126: Unexpected end of text. \ No newline at end of file +!!! error TS1160: Unterminated template literal. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringWithEmbeddedYieldKeyword.errors.txt b/tests/baselines/reference/templateStringWithEmbeddedYieldKeyword.errors.txt index b9e803a8a14..3cada665186 100644 --- a/tests/baselines/reference/templateStringWithEmbeddedYieldKeyword.errors.txt +++ b/tests/baselines/reference/templateStringWithEmbeddedYieldKeyword.errors.txt @@ -2,7 +2,7 @@ tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeyword.ts( tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeyword.ts(1,15): error TS1005: ';' expected. tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeyword.ts(3,26): error TS1158: Invalid template literal; expected '}' tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeyword.ts(3,30): error TS1159: Tagged templates are only available when targeting ECMAScript 6 and higher. -tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeyword.ts(5,1): error TS1126: Unexpected end of text. +tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeyword.ts(5,1): error TS1160: Unterminated template literal. tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeyword.ts(1,11): error TS2304: Cannot find name 'gen'. tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeyword.ts(3,20): error TS2304: Cannot find name 'yield'. tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeyword.ts(3,30): error TS2304: Cannot find name 'def'. @@ -31,4 +31,4 @@ tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeyword.ts( !!! error TS1159: Tagged templates are only available when targeting ECMAScript 6 and higher. -!!! error TS1126: Unexpected end of text. \ No newline at end of file +!!! error TS1160: Unterminated template literal. \ No newline at end of file diff --git a/tests/baselines/reference/templateStringWithEmbeddedYieldKeywordES6.errors.txt b/tests/baselines/reference/templateStringWithEmbeddedYieldKeywordES6.errors.txt index 6cae5332517..4e62197e031 100644 --- a/tests/baselines/reference/templateStringWithEmbeddedYieldKeywordES6.errors.txt +++ b/tests/baselines/reference/templateStringWithEmbeddedYieldKeywordES6.errors.txt @@ -1,7 +1,7 @@ tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6.ts(1,9): error TS1003: Identifier expected. tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6.ts(1,17): error TS1005: ';' expected. tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6.ts(3,26): error TS1158: Invalid template literal; expected '}' -tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6.ts(5,1): error TS1126: Unexpected end of text. +tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6.ts(5,1): error TS1160: Unterminated template literal. tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6.ts(1,11): error TS2304: Cannot find name 'gen'. tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6.ts(3,20): error TS2304: Cannot find name 'yield'. tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6.ts(3,30): error TS2304: Cannot find name 'def'. @@ -26,4 +26,4 @@ tests/cases/conformance/es6/templates/templateStringWithEmbeddedYieldKeywordES6. } -!!! error TS1126: Unexpected end of text. \ No newline at end of file +!!! error TS1160: Unterminated template literal. \ No newline at end of file diff --git a/tests/baselines/reference/unterminatedRegexAtEndOfSource1.errors.txt b/tests/baselines/reference/unterminatedRegexAtEndOfSource1.errors.txt index 2ee2e27c047..fa8959e90bf 100644 --- a/tests/baselines/reference/unterminatedRegexAtEndOfSource1.errors.txt +++ b/tests/baselines/reference/unterminatedRegexAtEndOfSource1.errors.txt @@ -1,10 +1,7 @@ -tests/cases/compiler/unterminatedRegexAtEndOfSource1.ts(1,9): error TS1109: Expression expected. -tests/cases/compiler/unterminatedRegexAtEndOfSource1.ts(1,10): error TS1109: Expression expected. +tests/cases/compiler/unterminatedRegexAtEndOfSource1.ts(1,10): error TS1161: Unterminated regular expression literal. -==== tests/cases/compiler/unterminatedRegexAtEndOfSource1.ts (2 errors) ==== +==== tests/cases/compiler/unterminatedRegexAtEndOfSource1.ts (1 errors) ==== var a = / - ~ -!!! error TS1109: Expression expected. -!!! error TS1109: Expression expected. \ No newline at end of file +!!! error TS1161: Unterminated regular expression literal. \ No newline at end of file diff --git a/tests/cases/fourslash/completionListInTemplateLiteralParts1.ts b/tests/cases/fourslash/completionListInTemplateLiteralParts1.ts index a71584bdbdd..0166546f63e 100644 --- a/tests/cases/fourslash/completionListInTemplateLiteralParts1.ts +++ b/tests/cases/fourslash/completionListInTemplateLiteralParts1.ts @@ -8,4 +8,4 @@ test.markers().forEach(marker => { goTo.position(marker.position); verify.completionListItemsCountIsGreaterThan(0) -}} \ No newline at end of file +}); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListInTemplateLiteralPartsNegatives1.ts b/tests/cases/fourslash/completionListInTemplateLiteralPartsNegatives1.ts index 1624192057b..ac64a41fb56 100644 --- a/tests/cases/fourslash/completionListInTemplateLiteralPartsNegatives1.ts +++ b/tests/cases/fourslash/completionListInTemplateLiteralPartsNegatives1.ts @@ -8,4 +8,4 @@ test.markers().forEach(marker => { goTo.position(marker.position); verify.completionListIsEmpty() -} \ No newline at end of file +}); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsInsideTemplates1.ts b/tests/cases/fourslash/findAllRefsInsideTemplates1.ts index e4501219265..dd4461751de 100644 --- a/tests/cases/fourslash/findAllRefsInsideTemplates1.ts +++ b/tests/cases/fourslash/findAllRefsInsideTemplates1.ts @@ -8,5 +8,5 @@ test.ranges().forEach(targetRange => { test.ranges().forEach(range => { verify.referencesAtPositionContains(range); - } -} \ No newline at end of file + }); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsInsideTemplates2.ts b/tests/cases/fourslash/findAllRefsInsideTemplates2.ts index cafddd4f45b..7f585234082 100644 --- a/tests/cases/fourslash/findAllRefsInsideTemplates2.ts +++ b/tests/cases/fourslash/findAllRefsInsideTemplates2.ts @@ -8,5 +8,5 @@ test.ranges().forEach(targetRange => { test.ranges().forEach(range => { verify.referencesAtPositionContains(range); - } -} \ No newline at end of file + }); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/formattingInMultilineComments.ts b/tests/cases/fourslash/formattingInMultilineComments.ts new file mode 100644 index 00000000000..7c58aa957ac --- /dev/null +++ b/tests/cases/fourslash/formattingInMultilineComments.ts @@ -0,0 +1,14 @@ +/// + +////var x = function() { +//// if (true) { +//// /*1*/} else {/*2*/ +////} +//// +////// newline at the end of the file + +goTo.marker("2"); +edit.insertLine(""); +goTo.marker("1"); +// else formating should not be affected +verify.currentLineContentIs(' } else {'); diff --git a/tests/cases/fourslash/getOccurrencesReturnBroken.ts b/tests/cases/fourslash/getOccurrencesReturnBroken.ts index e740e7f2bb3..08ec794f7e8 100644 --- a/tests/cases/fourslash/getOccurrencesReturnBroken.ts +++ b/tests/cases/fourslash/getOccurrencesReturnBroken.ts @@ -51,4 +51,4 @@ for (var i = 1; i <= test.markers().length; i++) { verify.occurrencesAtPositionCount(1); // 'return' is an instance member break; } -}); \ No newline at end of file +} \ No newline at end of file diff --git a/tests/cases/unittests/services/documentRegistry.ts b/tests/cases/unittests/services/documentRegistry.ts index 88503149715..044aea0095d 100644 --- a/tests/cases/unittests/services/documentRegistry.ts +++ b/tests/cases/unittests/services/documentRegistry.ts @@ -5,8 +5,8 @@ describe("DocumentRegistry", () => { var documentRegistry = ts.createDocumentRegistry(); var defaultCompilerOptions = ts.getDefaultCompilerOptions(); - var f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, TypeScript.ScriptSnapshot.fromString("var x = 1;"), "1", false); - var f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, TypeScript.ScriptSnapshot.fromString("var x = 1;"), "1", false); + var f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false); + var f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false); assert(f1 === f2, "DocumentRegistry should return the same document for the same name"); }); @@ -17,21 +17,21 @@ describe("DocumentRegistry", () => { // change compilation setting that doesn't affect parsing - should have the same document compilerOptions.declaration = true; - var f1 = documentRegistry.acquireDocument("file1.ts", compilerOptions, TypeScript.ScriptSnapshot.fromString("var x = 1;"), "1", false); + var f1 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false); compilerOptions.declaration = false; - var f2 = documentRegistry.acquireDocument("file1.ts", compilerOptions, TypeScript.ScriptSnapshot.fromString("var x = 1;"), "1", false); + var f2 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false); assert(f1 === f2, "Expected to have the same document instance"); // change value of compilation setting that is used during production of AST - new document is required compilerOptions.target = ts.ScriptTarget.ES3; - var f3 = documentRegistry.acquireDocument("file1.ts", compilerOptions, TypeScript.ScriptSnapshot.fromString("var x = 1;"), "1", false); + var f3 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false); assert(f1 !== f3, "Changed target: Expected to have different instances of document"); compilerOptions.module = ts.ModuleKind.CommonJS; - var f4 = documentRegistry.acquireDocument("file1.ts", compilerOptions, TypeScript.ScriptSnapshot.fromString("var x = 1;"), "1", false); + var f4 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), "1", false); assert(f1 !== f4, "Changed module: Expected to have different instances of document"); });