Merge branch 'master' into gotoDefShorthand
This commit is contained in:
commit
e6a1ac14bb
|
@ -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." },
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <number[]>[];
|
||||
},
|
||||
getChangeRange: (oldSnapshot: TypeScript.IScriptSnapshot) => {
|
||||
return <TypeScript.TextChangeRange>undefined;
|
||||
getChangeRange: (oldSnapshot: ts.IScriptSnapshot) => {
|
||||
return <ts.TextChangeRange>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('<MoveCaretToLineAndChar LineNumber="' + (lineCharPos.line() + 1) + '" CharNumber="' + (lineCharPos.character() + 1) + '" />');
|
||||
var lineStarts = ts.computeLineStarts(this.getCurrentFileContent());
|
||||
var lineCharPos = ts.getLineAndCharacterOfPosition(lineStarts, pos);
|
||||
this.scenarioActions.push('<MoveCaretToLineAndChar LineNumber="' + lineCharPos.line + '" CharNumber="' + lineCharPos.character + '" />');
|
||||
}
|
||||
|
||||
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'));
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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(<FunctionLikeDeclaration>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 = <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((<TypeAssertion>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((<DoStatement>node.parent).expression, node.parent));
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
|
||||
///<reference path='..\text.ts' />
|
||||
///<reference path='..\services.ts' />
|
||||
///<reference path='formattingContext.ts' />
|
||||
///<reference path='formattingRequestKind.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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
///<reference path='references.ts' />
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/// <reference path='services.ts' />
|
||||
/// <reference path="text/textSpan.ts" />
|
||||
|
||||
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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
/// <reference path="..\compiler\parser.ts"/>
|
||||
/// <reference path="..\compiler\checker.ts"/>
|
||||
|
||||
/// <reference path='syntax\incrementalParser.ts' />
|
||||
/// <reference path='text.ts' />
|
||||
/// <reference path='outliningElementsCollector.ts' />
|
||||
/// <reference path='navigationBar.ts' />
|
||||
/// <reference path='breakpoints.ts' />
|
||||
|
@ -13,17 +13,6 @@
|
|||
/// <reference path='smartIndenter.ts' />
|
||||
/// <reference path='formatting.ts' />
|
||||
|
||||
/// <reference path='core\references.ts' />
|
||||
/// <reference path='resources\references.ts' />
|
||||
/// <reference path='text\references.ts' />
|
||||
/// <reference path='syntax\references.ts' />
|
||||
/// <reference path='compiler\diagnostics.ts' />
|
||||
/// <reference path='compiler\hashTable.ts' />
|
||||
/// <reference path='compiler\ast.ts' />
|
||||
/// <reference path='compiler\astWalker.ts' />
|
||||
/// <reference path='compiler\astHelpers.ts' />
|
||||
/// <reference path='compiler\pathUtils.ts' />
|
||||
|
||||
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<string>;
|
||||
|
||||
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 = <SourceFileObject><any>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 ? (<Identifier>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,
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
|
||||
/// <reference path='services.ts' />
|
||||
|
||||
/// <reference path='compiler\pathUtils.ts' />
|
||||
|
||||
var debugObjectHost = (<any>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 = <ScriptSnapshotShimAdapter>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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
296
src/services/text.ts
Normal file
296
src/services/text.ts
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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'.
|
||||
|
|
@ -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.
|
||||
!!! error TS1161: Unterminated regular expression literal.
|
|
@ -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.
|
||||
!!! error TS1161: Unterminated regular expression literal.
|
|
@ -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'.
|
||||
|
||||
!!! error TS1161: Unterminated regular expression literal.
|
|
@ -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'.
|
||||
!!! error TS2304: Cannot find name 'foo'.
|
|
@ -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.
|
||||
!!! error TS1002: Unterminated string literal.
|
|
@ -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.
|
||||
!!! error TS1002: Unterminated string literal.
|
|
@ -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.
|
||||
!!! error TS1160: Unterminated template literal.
|
|
@ -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.
|
||||
!!! error TS1160: Unterminated template literal.
|
|
@ -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.
|
||||
!!! error TS1160: Unterminated template literal.
|
|
@ -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.
|
||||
!!! error TS1160: Unterminated template literal.
|
|
@ -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.
|
||||
!!! error TS1161: Unterminated regular expression literal.
|
|
@ -8,4 +8,4 @@ test.markers().forEach(marker => {
|
|||
goTo.position(marker.position);
|
||||
|
||||
verify.completionListItemsCountIsGreaterThan(0)
|
||||
}}
|
||||
});
|
|
@ -8,4 +8,4 @@ test.markers().forEach(marker => {
|
|||
goTo.position(marker.position);
|
||||
|
||||
verify.completionListIsEmpty()
|
||||
}
|
||||
});
|
|
@ -8,5 +8,5 @@ test.ranges().forEach(targetRange => {
|
|||
|
||||
test.ranges().forEach(range => {
|
||||
verify.referencesAtPositionContains(range);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
|
@ -8,5 +8,5 @@ test.ranges().forEach(targetRange => {
|
|||
|
||||
test.ranges().forEach(range => {
|
||||
verify.referencesAtPositionContains(range);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
14
tests/cases/fourslash/formattingInMultilineComments.ts
Normal file
14
tests/cases/fourslash/formattingInMultilineComments.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////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 {');
|
|
@ -51,4 +51,4 @@ for (var i = 1; i <= test.markers().length; i++) {
|
|||
verify.occurrencesAtPositionCount(1); // 'return' is an instance member
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
|
@ -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");
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue