From c2d4cd588797d3505321fc911f02dff4d76b5fd4 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 10 Dec 2014 13:45:08 -0800 Subject: [PATCH] Move TextSpan into the compiler layer. --- src/compiler/parser.ts | 2 + src/compiler/types.ts | 383 +++++++++++++++------ src/harness/fourslash.ts | 6 +- src/harness/harnessLanguageService.ts | 2 +- src/services/breakpoints.ts | 2 +- src/services/formatting.ts | 2 +- src/services/formatting/tokenSpan.ts | 5 - src/services/navigationBar.ts | 4 +- src/services/outliningElementsCollector.ts | 6 +- src/services/services.ts | 30 +- src/services/shims.ts | 6 +- src/services/signatureHelp.ts | 4 +- src/services/text.ts | 138 +------- tests/cases/unittests/incrementalParser.ts | 2 +- 14 files changed, 307 insertions(+), 285 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 7f6918c54fc..57300aa475c 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1185,6 +1185,8 @@ module ts { return sourceFile; } + + // Don't pass along the text change range for now. We'll pass it along once incremental // parsing is enabled. return parseSourceFile(newText, /*textChangeRange:*/ undefined, /*setNodeParents*/ true); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3bb937f6e69..48538173e67 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -279,18 +279,18 @@ module ts { } export const enum NodeFlags { - Export = 0x00000001, // Declarations - Ambient = 0x00000002, // Declarations - Public = 0x00000010, // Property/Method - Private = 0x00000020, // Property/Method - Protected = 0x00000040, // Property/Method - Static = 0x00000080, // Property/Method - MultiLine = 0x00000100, // Multi-line array or object literal - Synthetic = 0x00000200, // Synthetic node (for full fidelity) - DeclarationFile = 0x00000400, // Node is a .d.ts file - Let = 0x00000800, // Variable declaration - Const = 0x00001000, // Variable declaration - OctalLiteral = 0x00002000, + Export = 0x00000001, // Declarations + Ambient = 0x00000002, // Declarations + Public = 0x00000010, // Property/Method + Private = 0x00000020, // Property/Method + Protected = 0x00000040, // Property/Method + Static = 0x00000080, // Property/Method + MultiLine = 0x00000100, // Multi-line array or object literal + Synthetic = 0x00000200, // Synthetic node (for full fidelity) + DeclarationFile = 0x00000400, // Node is a .d.ts file + Let = 0x00000800, // Variable declaration + Const = 0x00001000, // Variable declaration + OctalLiteral = 0x00002000, Modifier = Export | Ambient | Public | Private | Protected | Static, AccessibilityModifier = Public | Private | Protected, @@ -595,7 +595,7 @@ module ts { export interface VoidExpression extends UnaryExpression { expression: UnaryExpression; } - + export interface YieldExpression extends Expression { asteriskToken?: Node; expression: Expression; @@ -871,7 +871,7 @@ module ts { getPositionFromLineAndCharacter(line: number, character: number): number; getLineStarts(): number[]; - // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter + // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter // indicates what changed between the 'text' that this SourceFile has and the 'newText'. // The SourceFile will be created with the compiler attempting to reuse as many nodes from // this file as possible. @@ -1032,25 +1032,25 @@ module ts { } export const enum TypeFormatFlags { - None = 0x00000000, - WriteArrayAsGenericType = 0x00000001, // Write Array instead T[] - UseTypeOfFunction = 0x00000002, // Write typeof instead of function type literal - NoTruncation = 0x00000004, // Don't truncate typeToString result - WriteArrowStyleSignature = 0x00000008, // Write arrow style signature - WriteOwnNameForAnyLike = 0x00000010, // Write symbol's own name instead of 'any' for any like types (eg. unknown, __resolving__ etc) - WriteTypeArgumentsOfSignature = 0x00000020, // Write the type arguments instead of type parameters of the signature - InElementType = 0x00000040, // Writing an array or union element type + None = 0x00000000, + WriteArrayAsGenericType = 0x00000001, // Write Array instead T[] + UseTypeOfFunction = 0x00000002, // Write typeof instead of function type literal + NoTruncation = 0x00000004, // Don't truncate typeToString result + WriteArrowStyleSignature = 0x00000008, // Write arrow style signature + WriteOwnNameForAnyLike = 0x00000010, // Write symbol's own name instead of 'any' for any like types (eg. unknown, __resolving__ etc) + WriteTypeArgumentsOfSignature = 0x00000020, // Write the type arguments instead of type parameters of the signature + InElementType = 0x00000040, // Writing an array or union element type } export const enum SymbolFormatFlags { - None = 0x00000000, - WriteTypeParametersOrArguments = 0x00000001, // Write symbols's type argument if it is instantiated symbol - // eg. class C { p: T } <-- Show p as C.p here - // var a: C; - // var p = a.p; <--- Here p is property of C so show it as C.p instead of just C.p - UseOnlyExternalAliasing = 0x00000002, // Use only external alias information to get the symbol name in the given context - // eg. module m { export class c { } } import x = m.c; - // When this flag is specified m.c will be used to refer to the class instead of alias symbol x + None = 0x00000000, + WriteTypeParametersOrArguments = 0x00000001, // Write symbols's type argument if it is instantiated symbol + // eg. class C { p: T } <-- Show p as C.p here + // var a: C; + // var p = a.p; <--- Here p is property of C so show it as C.p instead of just C.p + UseOnlyExternalAliasing = 0x00000002, // Use only external alias information to get the symbol name in the given context + // eg. module m { export class c { } } import x = m.c; + // When this flag is specified m.c will be used to refer to the class instead of alias symbol x } export const enum SymbolAccessibility { @@ -1094,45 +1094,45 @@ module ts { export const enum SymbolFlags { FunctionScopedVariable = 0x00000001, // Variable (var) or parameter - BlockScopedVariable = 0x00000002, // A block-scoped variable (let or const) - Property = 0x00000004, // Property or enum member - EnumMember = 0x00000008, // Enum member - Function = 0x00000010, // Function - Class = 0x00000020, // Class - Interface = 0x00000040, // Interface - ConstEnum = 0x00000080, // Const enum - RegularEnum = 0x00000100, // Enum - ValueModule = 0x00000200, // Instantiated module - NamespaceModule = 0x00000400, // Uninstantiated module - TypeLiteral = 0x00000800, // Type Literal - ObjectLiteral = 0x00001000, // Object Literal - Method = 0x00002000, // Method - Constructor = 0x00004000, // Constructor - GetAccessor = 0x00008000, // Get accessor - SetAccessor = 0x00010000, // Set accessor - Signature = 0x00020000, // Call, construct, or index signature - TypeParameter = 0x00040000, // Type parameter - TypeAlias = 0x00080000, // Type alias + BlockScopedVariable = 0x00000002, // A block-scoped variable (let or const) + Property = 0x00000004, // Property or enum member + EnumMember = 0x00000008, // Enum member + Function = 0x00000010, // Function + Class = 0x00000020, // Class + Interface = 0x00000040, // Interface + ConstEnum = 0x00000080, // Const enum + RegularEnum = 0x00000100, // Enum + ValueModule = 0x00000200, // Instantiated module + NamespaceModule = 0x00000400, // Uninstantiated module + TypeLiteral = 0x00000800, // Type Literal + ObjectLiteral = 0x00001000, // Object Literal + Method = 0x00002000, // Method + Constructor = 0x00004000, // Constructor + GetAccessor = 0x00008000, // Get accessor + SetAccessor = 0x00010000, // Set accessor + Signature = 0x00020000, // Call, construct, or index signature + TypeParameter = 0x00040000, // Type parameter + TypeAlias = 0x00080000, // Type alias // Export markers (see comment in declareModuleMember in binder) - ExportValue = 0x00100000, // Exported value marker - ExportType = 0x00200000, // Exported type marker - ExportNamespace = 0x00400000, // Exported namespace marker - Import = 0x00800000, // Import - Instantiated = 0x01000000, // Instantiated symbol - Merged = 0x02000000, // Merged symbol (created during program binding) - Transient = 0x04000000, // Transient symbol (created during type check) - Prototype = 0x08000000, // Prototype property (no source representation) - UnionProperty = 0x10000000, // Property in union type - Optional = 0x20000000, // Optional property + ExportValue = 0x00100000, // Exported value marker + ExportType = 0x00200000, // Exported type marker + ExportNamespace = 0x00400000, // Exported namespace marker + Import = 0x00800000, // Import + Instantiated = 0x01000000, // Instantiated symbol + Merged = 0x02000000, // Merged symbol (created during program binding) + Transient = 0x04000000, // Transient symbol (created during type check) + Prototype = 0x08000000, // Prototype property (no source representation) + UnionProperty = 0x10000000, // Property in union type + Optional = 0x20000000, // Optional property - Enum = RegularEnum | ConstEnum, - Variable = FunctionScopedVariable | BlockScopedVariable, - Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor, - Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias, + Enum = RegularEnum | ConstEnum, + Variable = FunctionScopedVariable | BlockScopedVariable, + Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor, + Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias, Namespace = ValueModule | NamespaceModule, - Module = ValueModule | NamespaceModule, - Accessor = GetAccessor | SetAccessor, + Module = ValueModule | NamespaceModule, + Accessor = GetAccessor | SetAccessor, // Variables can be redeclared, but can not redeclare a block-scoped declaration with the // same name, or any other value that is not a variable, e.g. ValueModule or Class @@ -1142,34 +1142,34 @@ module ts { // they can not merge with anything in the value space BlockScopedVariableExcludes = Value, - ParameterExcludes = Value, - PropertyExcludes = Value, - EnumMemberExcludes = Value, - FunctionExcludes = Value & ~(Function | ValueModule), - ClassExcludes = (Value | Type) & ~ValueModule, - InterfaceExcludes = Type & ~Interface, - RegularEnumExcludes = (Value | Type) & ~(RegularEnum | ValueModule), // regular enums merge only with regular enums and modules - ConstEnumExcludes = (Value | Type) & ~ConstEnum, // const enums merge only with const enums - ValueModuleExcludes = Value & ~(Function | Class | RegularEnum | ValueModule), + ParameterExcludes = Value, + PropertyExcludes = Value, + EnumMemberExcludes = Value, + FunctionExcludes = Value & ~(Function | ValueModule), + ClassExcludes = (Value | Type) & ~ValueModule, + InterfaceExcludes = Type & ~Interface, + RegularEnumExcludes = (Value | Type) & ~(RegularEnum | ValueModule), // regular enums merge only with regular enums and modules + ConstEnumExcludes = (Value | Type) & ~ConstEnum, // const enums merge only with const enums + ValueModuleExcludes = Value & ~(Function | Class | RegularEnum | ValueModule), NamespaceModuleExcludes = 0, - MethodExcludes = Value & ~Method, - GetAccessorExcludes = Value & ~SetAccessor, - SetAccessorExcludes = Value & ~GetAccessor, - TypeParameterExcludes = Type & ~TypeParameter, - TypeAliasExcludes = Type, - ImportExcludes = Import, // Imports collide with all other imports with the same name + MethodExcludes = Value & ~Method, + GetAccessorExcludes = Value & ~SetAccessor, + SetAccessorExcludes = Value & ~GetAccessor, + TypeParameterExcludes = Type & ~TypeParameter, + TypeAliasExcludes = Type, + ImportExcludes = Import, // Imports collide with all other imports with the same name ModuleMember = Variable | Function | Class | Interface | Enum | Module | TypeAlias | Import, ExportHasLocal = Function | Class | Enum | ValueModule, - HasLocals = Function | Module | Method | Constructor | Accessor | Signature, + HasLocals = Function | Module | Method | Constructor | Accessor | Signature, HasExports = Class | Enum | Module, HasMembers = Class | Interface | TypeLiteral | ObjectLiteral, - IsContainer = HasLocals | HasExports | HasMembers, + IsContainer = HasLocals | HasExports | HasMembers, PropertyOrAccessor = Property | Accessor, - Export = ExportNamespace | ExportType | ExportValue, + Export = ExportNamespace | ExportType | ExportValue, } export interface Symbol { @@ -1203,13 +1203,13 @@ module ts { } export const enum NodeCheckFlags { - TypeChecked = 0x00000001, // Node has been type checked - LexicalThis = 0x00000002, // Lexical 'this' reference - CaptureThis = 0x00000004, // Lexical 'this' used in body - EmitExtends = 0x00000008, // Emit __extends - SuperInstance = 0x00000010, // Instance 'super' reference - SuperStatic = 0x00000020, // Static 'super' reference - ContextChecked = 0x00000040, // Contextual types have been assigned + TypeChecked = 0x00000001, // Node has been type checked + LexicalThis = 0x00000002, // Lexical 'this' reference + CaptureThis = 0x00000004, // Lexical 'this' used in body + EmitExtends = 0x00000008, // Emit __extends + SuperInstance = 0x00000010, // Instance 'super' reference + SuperStatic = 0x00000020, // Static 'super' reference + ContextChecked = 0x00000040, // Contextual types have been assigned // Values for enum members have been computed, and any errors have been reported for them. EnumValuesComputed = 0x00000080, @@ -1228,26 +1228,26 @@ module ts { } export const enum TypeFlags { - Any = 0x00000001, - String = 0x00000002, - Number = 0x00000004, - Boolean = 0x00000008, - Void = 0x00000010, - Undefined = 0x00000020, - Null = 0x00000040, - Enum = 0x00000080, // Enum type - StringLiteral = 0x00000100, // String literal type - TypeParameter = 0x00000200, // Type parameter - Class = 0x00000400, // Class - Interface = 0x00000800, // Interface - Reference = 0x00001000, // Generic type reference - Tuple = 0x00002000, // Tuple - Union = 0x00004000, // Union - Anonymous = 0x00008000, // Anonymous - FromSignature = 0x00010000, // Created for signature assignment check - Unwidened = 0x00020000, // Unwidened type (is or contains Undefined or Null type) + Any = 0x00000001, + String = 0x00000002, + Number = 0x00000004, + Boolean = 0x00000008, + Void = 0x00000010, + Undefined = 0x00000020, + Null = 0x00000040, + Enum = 0x00000080, // Enum type + StringLiteral = 0x00000100, // String literal type + TypeParameter = 0x00000200, // Type parameter + Class = 0x00000400, // Class + Interface = 0x00000800, // Interface + Reference = 0x00001000, // Generic type reference + Tuple = 0x00002000, // Tuple + Union = 0x00004000, // Union + Anonymous = 0x00008000, // Anonymous + FromSignature = 0x00010000, // Created for signature assignment check + Unwidened = 0x00020000, // Unwidened type (is or contains Undefined or Null type) - Intrinsic = Any | String | Number | Boolean | Void | Undefined | Null, + Intrinsic = Any | String | Number | Boolean | Void | Undefined | Null, StringLike = String | StringLiteral, NumberLike = Number | Enum, ObjectType = Class | Interface | Reference | Tuple | Anonymous, @@ -1365,7 +1365,7 @@ module ts { inferences: TypeInferences[]; // Inferences made for each type parameter inferredTypes: Type[]; // Inferred type for each type parameter failedTypeParameterIndex?: number; // Index of type parameter for which inference failed - // It is optional because in contextual signature instantiation, nothing fails + // It is optional because in contextual signature instantiation, nothing fails } export interface DiagnosticMessage { @@ -1498,7 +1498,7 @@ module ts { narrowNoBreakSpace = 0x202F, ideographicSpace = 0x3000, mathematicalSpace = 0x205F, - ogham = 0x1680, + ogham = 0x1680, _ = 0x5F, $ = 0x24, @@ -1604,7 +1604,7 @@ module ts { tab = 0x09, // \t verticalTab = 0x0B, // \v } - + export interface CancellationToken { isCancellationRequested(): boolean; } @@ -1641,4 +1641,161 @@ module ts { intersectsWithPosition(position: number): boolean; intersection(span: TextSpan): TextSpan; } -} + + /** + * Creates a TextSpan instance beginning with the position Start and having the Length + * specified with length. + */ + /* + export function createTextSpan(start: number, length: number): TextSpan { + Debug.assert(start >= 0, "start"); + Debug.assert(length >= 0, "length"); + + function end() { + return start + length; + } + + function overlapsWith(span: TextSpan): boolean { + var overlapStart = Math.max(start, span.start()); + var overlapEnd = Math.min(end(), span.end()); + + return overlapStart < overlapEnd; + } + + function overlap(span: TextSpan): TextSpan { + var overlapStart = Math.max(start, span.start()); + var overlapEnd = Math.min(end(), span.end()); + + if (overlapStart < overlapEnd) { + return createTextSpanFromBounds(overlapStart, overlapEnd); + } + + return undefined; + } + + function intersectsWithTextSpan(span: TextSpan): boolean { + return span.start() <= end() && span.end() >= start; + } + + function intersectsWith(_start: number, _length: number): boolean { + var _end = _start + _length; + return _start <= end() && _end >= start; + } + + function intersectsWithPosition(position: number): boolean { + return position <= end() && position >= start; + } + + function intersection(span: TextSpan): TextSpan { + var intersectStart = Math.max(start, span.start()); + var intersectEnd = Math.min(end(), span.end()); + + if (intersectStart <= intersectEnd) { + return createTextSpanFromBounds(intersectStart, intersectEnd); + } + + return undefined; + } + + + return { + start: () => start, length: () => length, + toJSON: key => { start, length }, + end: end, + isEmpty: () => length === 0, + containsPosition: position => position >= start && position < end(), + containsTextSpan: span => span.start() >= start && span.end() <= end(), + overlapsWith: overlapsWith, + overlap: overlap, + intersectsWithTextSpan: intersectsWithTextSpan, + intersectsWith: intersectsWith, + intersectsWithPosition: intersectsWithPosition, + intersection: intersection, + } + } + */ + + export function createTextSpanFromBounds(start: number, end: number) { + return createTextSpan(start, end - start); + } + + export function createTextSpan(start: number, length: number): TextSpan { + return new (textSpanConstructor)(start, length); + } + + var textSpanConstructor = (function () { + function TextSpanObject(start: number, length: number) { + ts.Debug.assert(start >= 0, "start"); + ts.Debug.assert(length >= 0, "length"); + this._start = start; + this._length = length; + } + + TextSpanObject.prototype.toJSON = function (key: string) { + return { start: this._start, length: this._length }; + }; + + TextSpanObject.prototype.start = function () { + return this._start; + }; + + TextSpanObject.prototype.length = function () { + return this._length; + }; + + TextSpanObject.prototype.end = function () { + return this._start + this._length; + }; + + TextSpanObject.prototype.isEmpty = function () { + return this._length === 0; + }; + + TextSpanObject.prototype.containsPosition = function (position: number) { + return position >= this._start && position < this.end(); + }; + + TextSpanObject.prototype.containsTextSpan = function (span: TextSpan) { + return span.start() >= this._start && span.end() <= this.end(); + }; + + TextSpanObject.prototype.overlapsWith = function (span: TextSpan) { + var overlapStart = Math.max(this._start, span.start()); + var overlapEnd = Math.min(this.end(), span.end()); + return overlapStart < overlapEnd; + }; + + TextSpanObject.prototype.overlap = function (span: TextSpan) { + var overlapStart = Math.max(this._start, span.start()); + var overlapEnd = Math.min(this.end(), span.end()); + if (overlapStart < overlapEnd) { + return createTextSpanFromBounds(overlapStart, overlapEnd); + } + return undefined; + }; + + TextSpanObject.prototype.intersectsWithTextSpan = function (span: TextSpan) { + return span.start() <= this.end() && span.end() >= this._start; + }; + + TextSpanObject.prototype.intersectsWith = function (start: number, length: number) { + var end = start + length; + return start <= this.end() && end >= this._start; + }; + + TextSpanObject.prototype.intersectsWithPosition = function (position: number) { + return position <= this.end() && position >= this._start; + }; + + TextSpanObject.prototype.intersection = function (span: TextSpan) { + var intersectStart = Math.max(this._start, span.start()); + var intersectEnd = Math.min(this.end(), span.end()); + if (intersectStart <= intersectEnd) { + return createTextSpanFromBounds(intersectStart, intersectEnd); + } + return undefined; + }; + + return TextSpanObject; + })(); +} \ No newline at end of file diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index c88364de8b8..29a25a9923e 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1755,14 +1755,14 @@ module FourSlash { public verifySemanticClassifications(expected: { classificationType: string; text: string }[]) { var actual = this.languageService.getSemanticClassifications(this.activeFile.fileName, - new ts.TextSpanObject(0, this.activeFile.content.length)); + ts.createTextSpan(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 ts.TextSpanObject(0, this.activeFile.content.length)); + ts.createTextSpan(0, this.activeFile.content.length)); this.verifyClassifications(expected, actual); } @@ -1796,7 +1796,7 @@ module FourSlash { for (var i = 0; i < spans.length; i++) { var expectedSpan = spans[i]; var actualComment = actual[i]; - var actualCommentSpan = new ts.TextSpanObject(actualComment.position, actualComment.message.length); + var actualCommentSpan = ts.createTextSpan(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() + ')'); diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index c4a75772529..deefb2a4052 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -33,7 +33,7 @@ module Harness.LanguageService { this.editRanges.push({ length: this.content.length, textChangeRange: new ts.TextChangeRangeObject( - ts.TextSpanObject.fromBounds(minChar, limChar), newText.length) + ts.createTextSpanFromBounds(minChar, limChar), newText.length) }); // Update version # diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 4e4ad585503..e96a1974b2a 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -38,7 +38,7 @@ module ts.BreakpointResolver { return spanInNode(tokenAtLocation); function textSpan(startNode: Node, endNode?: Node) { - return TextSpanObject.fromBounds(startNode.getStart(), (endNode || startNode).getEnd()); + return createTextSpanFromBounds(startNode.getStart(), (endNode || startNode).getEnd()); } function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan { diff --git a/src/services/formatting.ts b/src/services/formatting.ts index 0cba03664d4..55e2a5832c4 100644 --- a/src/services/formatting.ts +++ b/src/services/formatting.ts @@ -868,7 +868,7 @@ module ts.formatting { } function newTextChange(start: number, len: number, newText: string): TextChange { - return { span: new TextSpanObject(start, len), newText } + return { span: createTextSpan(start, len), newText } } function recordDelete(start: number, len: number) { diff --git a/src/services/formatting/tokenSpan.ts b/src/services/formatting/tokenSpan.ts index dd328931919..926035094b1 100644 --- a/src/services/formatting/tokenSpan.ts +++ b/src/services/formatting/tokenSpan.ts @@ -16,9 +16,4 @@ /// module ts.formatting { - export class TokenSpan extends TextSpanObject { - constructor(public kind: SyntaxKind, start: number, length: number) { - super(start, length); - } - } } \ No newline at end of file diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index cfa3c98beb7..e7a500e2e9a 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -462,8 +462,8 @@ module ts.NavigationBar { function getNodeSpan(node: Node) { return node.kind === SyntaxKind.SourceFile - ? TextSpanObject.fromBounds(node.getFullStart(), node.getEnd()) - : TextSpanObject.fromBounds(node.getStart(), node.getEnd()); + ? createTextSpanFromBounds(node.getFullStart(), node.getEnd()) + : createTextSpanFromBounds(node.getStart(), node.getEnd()); } function getTextOfNode(node: Node): string { diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 9cbd2a69a38..5f44a2633a3 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -38,8 +38,8 @@ module ts { function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean) { if (hintSpanNode && startElement && endElement) { var span: OutliningSpan = { - textSpan: TextSpanObject.fromBounds(startElement.pos, endElement.end), - hintSpan: TextSpanObject.fromBounds(hintSpanNode.getStart(), hintSpanNode.end), + textSpan: createTextSpanFromBounds(startElement.pos, endElement.end), + hintSpan: createTextSpanFromBounds(hintSpanNode.getStart(), hintSpanNode.end), bannerText: collapseText, autoCollapse: autoCollapse }; @@ -88,7 +88,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 = TextSpanObject.fromBounds(n.getStart(), n.end); + var span = createTextSpanFromBounds(n.getStart(), n.end); elements.push({ textSpan: span, hintSpan: span, diff --git a/src/services/services.ts b/src/services/services.ts index 93545fdaf8d..569754ffaba 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3219,7 +3219,7 @@ module ts { return { kind: ScriptElementKind.unknown, kindModifiers: ScriptElementKindModifier.none, - textSpan: new TextSpanObject(node.getStart(), node.getWidth()), + textSpan: createTextSpan(node.getStart(), node.getWidth()), displayParts: typeToDisplayParts(typeInfoResolver, type, getContainerNode(node)), documentation: type.symbol ? type.symbol.getDocumentationComment() : undefined }; @@ -3233,7 +3233,7 @@ module ts { return { kind: displayPartsDocumentationsAndKind.symbolKind, kindModifiers: getSymbolModifiers(symbol), - textSpan: new TextSpanObject(node.getStart(), node.getWidth()), + textSpan: createTextSpan(node.getStart(), node.getWidth()), displayParts: displayPartsDocumentationsAndKind.displayParts, documentation: displayPartsDocumentationsAndKind.documentation }; @@ -3244,7 +3244,7 @@ module ts { function getDefinitionInfo(node: Node, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo { return { fileName: node.getSourceFile().filename, - textSpan: TextSpanObject.fromBounds(node.getStart(), node.getEnd()), + textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()), kind: symbolKind, name: symbolName, containerKind: undefined, @@ -3321,7 +3321,7 @@ module ts { if (referenceFile) { return [{ fileName: referenceFile.filename, - textSpan: TextSpanObject.fromBounds(0, 0), + textSpan: createTextSpanFromBounds(0, 0), kind: ScriptElementKind.scriptElement, name: comment.filename, containerName: undefined, @@ -3512,7 +3512,7 @@ module ts { if (shouldHighlightNextKeyword) { result.push({ fileName: filename, - textSpan: TextSpanObject.fromBounds(elseKeyword.getStart(), ifKeyword.end), + textSpan: createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end), isWriteAccess: false }); i++; // skip the next keyword @@ -4204,7 +4204,7 @@ module ts { (findInComments && isInComment(position))) { result.push({ fileName: sourceFile.filename, - textSpan: new TextSpanObject(position, searchText.length), + textSpan: createTextSpan(position, searchText.length), isWriteAccess: false }); } @@ -4587,7 +4587,7 @@ module ts { return { fileName: node.getSourceFile().filename, - textSpan: TextSpanObject.fromBounds(start, end), + textSpan: createTextSpanFromBounds(start, end), isWriteAccess: isWriteAccess(node) }; } @@ -4643,7 +4643,7 @@ module ts { kindModifiers: getNodeModifiers(declaration), matchKind: MatchKind[matchKind], fileName: filename, - textSpan: TextSpanObject.fromBounds(declaration.getStart(), declaration.getEnd()), + textSpan: createTextSpanFromBounds(declaration.getStart(), declaration.getEnd()), // TODO(jfreeman): What should be the containerName when the container has a computed name? containerName: container && container.name ? (container.name).text : "", containerKind: container && container.name ? getNodeKind(container) : "" @@ -4920,7 +4920,7 @@ module ts { } } - return TextSpanObject.fromBounds(nodeForStartPos.getStart(), node.getEnd()); + return createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd()); } function getBreakpointStatementAtPosition(filename: string, position: number) { @@ -4997,7 +4997,7 @@ module ts { var type = classifySymbol(symbol, getMeaningFromLocation(node)); if (type) { result.push({ - textSpan: new TextSpanObject(node.getStart(), node.getWidth()), + textSpan: createTextSpan(node.getStart(), node.getWidth()), classificationType: type }); } @@ -5023,7 +5023,7 @@ module ts { var width = comment.end - comment.pos; if (span.intersectsWith(comment.pos, width)) { result.push({ - textSpan: new TextSpanObject(comment.pos, width), + textSpan: createTextSpan(comment.pos, width), classificationType: ClassificationTypeNames.comment }); } @@ -5036,7 +5036,7 @@ module ts { var type = classifyTokenType(token); if (type) { result.push({ - textSpan: new TextSpanObject(token.getStart(), token.getWidth()), + textSpan: createTextSpan(token.getStart(), token.getWidth()), classificationType: type }); } @@ -5164,8 +5164,8 @@ module ts { var current = childNodes[i]; if (current.kind === matchKind) { - var range1 = new TextSpanObject(token.getStart(sourceFile), token.getWidth(sourceFile)); - var range2 = new TextSpanObject(current.getStart(sourceFile), current.getWidth(sourceFile)); + var range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); + var range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); // We want to order the braces when we return the result. if (range1.start() < range2.start()) { @@ -5416,7 +5416,7 @@ module ts { if (kind) { return getRenameInfo(symbol.name, typeInfoResolver.getFullyQualifiedName(symbol), kind, getSymbolModifiers(symbol), - new TextSpanObject(node.getStart(), node.getWidth())); + createTextSpan(node.getStart(), node.getWidth())); } } } diff --git a/src/services/shims.ts b/src/services/shims.ts index 1bafbafa005..c07ef320fdb 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -329,7 +329,7 @@ module ts { var decoded: { span: { start: number; length: number; }; newLength: number; } = JSON.parse(encoded); return new TextChangeRangeObject( - new TextSpanObject(decoded.span.start, decoded.span.length), decoded.newLength); + createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength); } } @@ -510,7 +510,7 @@ module ts { return this.forwardJSONCall( "getSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", () => { - var classifications = this.languageService.getSyntacticClassifications(fileName, new TextSpanObject(start, length)); + var classifications = this.languageService.getSyntacticClassifications(fileName, createTextSpan(start, length)); return classifications; }); } @@ -519,7 +519,7 @@ module ts { return this.forwardJSONCall( "getSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", () => { - var classifications = this.languageService.getSemanticClassifications(fileName, new TextSpanObject(start, length)); + var classifications = this.languageService.getSemanticClassifications(fileName, createTextSpan(start, length)); return classifications; }); } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 9291bd0d685..426bd732882 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -367,7 +367,7 @@ module ts.SignatureHelp { // but not including parentheses) var applicableSpanStart = argumentsList.getFullStart(); var applicableSpanEnd = skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false); - return new TextSpanObject(applicableSpanStart, applicableSpanEnd - applicableSpanStart); + return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } function getApplicableSpanForTaggedTemplate(taggedTemplate: TaggedTemplateExpression): TextSpan { @@ -391,7 +391,7 @@ module ts.SignatureHelp { } } - return new TextSpanObject(applicableSpanStart, applicableSpanEnd - applicableSpanStart); + return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } function getContainingArgumentInfo(node: Node): ArgumentListInfo { diff --git a/src/services/text.ts b/src/services/text.ts index 85465ffdf46..05b460cda08 100644 --- a/src/services/text.ts +++ b/src/services/text.ts @@ -1,138 +1,6 @@ module ts { - export class TextSpanObject { - 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 TextSpanObject.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 TextSpanObject.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 TextSpanObject(start, end - start); - } - } - export class TextChangeRangeObject implements TextChangeRange { - public static unchanged = new TextChangeRangeObject(new TextSpanObject(0, 0), 0); + public static unchanged = new TextChangeRangeObject(createTextSpan(0, 0), 0); private _span: TextSpan; private _newLength: number; @@ -162,7 +30,7 @@ module ts { } public newSpan(): TextSpan { - return new TextSpanObject(this.span().start(), this.newLength()); + return createTextSpan(this.span().start(), this.newLength()); } public isUnchanged(): boolean { @@ -290,7 +158,7 @@ module ts { newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2)); } - return new TextChangeRangeObject(TextSpanObject.fromBounds(oldStartN, oldEndN), /*newLength: */newEndN - oldStartN); + return new TextChangeRangeObject(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength: */newEndN - oldStartN); } } } \ No newline at end of file diff --git a/tests/cases/unittests/incrementalParser.ts b/tests/cases/unittests/incrementalParser.ts index 9bd9df5deca..4cd816a3a3a 100644 --- a/tests/cases/unittests/incrementalParser.ts +++ b/tests/cases/unittests/incrementalParser.ts @@ -6,7 +6,7 @@ module ts { var contents = text.getText(0, text.getLength()); var newContents = contents.substr(0, start) + newText + contents.substring(start + length); - return { text: ScriptSnapshot.fromString(newContents), textChangeRange: new TextChangeRangeObject(new TextSpanObject(start, length), newText.length) } + return { text: ScriptSnapshot.fromString(newContents), textChangeRange: new TextChangeRangeObject(createTextSpan(start, length), newText.length) } } function withInsert(text: IScriptSnapshot, start: number, newText: string): { text: IScriptSnapshot; textChangeRange: TextChangeRange; } {