mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into report-multiple-overload-errors
This commit is contained in:
@@ -4998,7 +4998,10 @@
|
||||
"category": "Message",
|
||||
"code": 95079
|
||||
},
|
||||
|
||||
"Infer 'this' type of '{0}' from usage": {
|
||||
"category": "Message",
|
||||
"code": 95080
|
||||
},
|
||||
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
|
||||
"category": "Error",
|
||||
"code": 18004
|
||||
|
||||
@@ -2204,6 +2204,13 @@ namespace ts {
|
||||
return tag;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function createJSDocThisTag(typeExpression?: JSDocTypeExpression): JSDocThisTag {
|
||||
const tag = createJSDocTag<JSDocThisTag>(SyntaxKind.JSDocThisTag, "this");
|
||||
tag.typeExpression = typeExpression;
|
||||
return tag;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function createJSDocParamTag(name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, comment?: string): JSDocParameterTag {
|
||||
const tag = createJSDocTag<JSDocParameterTag>(SyntaxKind.JSDocParameterTag, "param");
|
||||
|
||||
@@ -5187,6 +5187,9 @@ namespace ts {
|
||||
return node.parent.left.name;
|
||||
}
|
||||
}
|
||||
else if (isVariableDeclaration(node.parent) && isIdentifier(node.parent.name)) {
|
||||
return node.parent.name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -395,8 +395,15 @@ namespace ts.server {
|
||||
const locations: RenameLocation[] = [];
|
||||
for (const entry of body.locs) {
|
||||
const fileName = entry.file;
|
||||
for (const { start, end, ...prefixSuffixText } of entry.locs) {
|
||||
locations.push({ textSpan: this.decodeSpan({ start, end }, fileName), fileName, ...prefixSuffixText });
|
||||
for (const { start, end, contextStart, contextEnd, ...prefixSuffixText } of entry.locs) {
|
||||
locations.push({
|
||||
textSpan: this.decodeSpan({ start, end }, fileName),
|
||||
fileName,
|
||||
...(contextStart !== undefined ?
|
||||
{ contextSpan: this.decodeSpan({ start: contextStart, end: contextEnd! }, fileName) } :
|
||||
undefined),
|
||||
...prefixSuffixText
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+35
-15
@@ -42,6 +42,7 @@ namespace FourSlash {
|
||||
* is a range with `text in range` "selected".
|
||||
*/
|
||||
ranges: Range[];
|
||||
rangesByText?: ts.MultiMap<Range>;
|
||||
}
|
||||
|
||||
export interface Marker {
|
||||
@@ -955,12 +956,15 @@ namespace FourSlash {
|
||||
const fullExpected = ts.map<FourSlashInterface.ReferenceGroup, ReferenceGroupJson>(parts, ({ definition, ranges }) => ({
|
||||
definition: typeof definition === "string" ? definition : { ...definition, range: ts.createTextSpanFromRange(definition.range) },
|
||||
references: ranges.map<ts.ReferenceEntry>(r => {
|
||||
const { isWriteAccess = false, isDefinition = false, isInString } = (r.marker && r.marker.data || {}) as { isWriteAccess?: boolean, isDefinition?: boolean, isInString?: true };
|
||||
const { isWriteAccess = false, isDefinition = false, isInString, contextRangeIndex } = (r.marker && r.marker.data || {}) as { isWriteAccess?: boolean, isDefinition?: boolean, isInString?: true, contextRangeIndex?: number };
|
||||
return {
|
||||
fileName: r.fileName,
|
||||
textSpan: ts.createTextSpanFromRange(r),
|
||||
isWriteAccess,
|
||||
isDefinition,
|
||||
...(contextRangeIndex !== undefined ?
|
||||
{ contextSpan: ts.createTextSpanFromRange(this.getRanges()[contextRangeIndex]) } :
|
||||
undefined),
|
||||
...(isInString ? { isInString: true } : undefined),
|
||||
};
|
||||
}),
|
||||
@@ -997,8 +1001,8 @@ namespace FourSlash {
|
||||
assert.deepEqual<ReadonlyArray<ts.ReferenceEntry> | undefined>(refs, expected);
|
||||
}
|
||||
|
||||
public verifySingleReferenceGroup(definition: FourSlashInterface.ReferenceGroupDefinition, ranges?: Range[]) {
|
||||
ranges = ranges || this.getRanges();
|
||||
public verifySingleReferenceGroup(definition: FourSlashInterface.ReferenceGroupDefinition, ranges?: Range[] | string) {
|
||||
ranges = ts.isString(ranges) ? this.rangesByText().get(ranges)! : ranges || this.getRanges();
|
||||
this.verifyReferenceGroups(ranges, [{ definition, ranges }]);
|
||||
}
|
||||
|
||||
@@ -1011,7 +1015,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
};
|
||||
|
||||
if ((actual === undefined) !== (expected === undefined)) {
|
||||
fail(`Expected ${expected}, got ${actual}`);
|
||||
fail(`Expected ${stringify(expected)}, got ${stringify(actual)}`);
|
||||
}
|
||||
|
||||
for (const key in actual) {
|
||||
@@ -1021,7 +1025,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
recur(ak, ek, path ? path + "." + key : key);
|
||||
}
|
||||
else if (ak !== ek) {
|
||||
fail(`Expected '${key}' to be '${ek}', got '${ak}'`);
|
||||
fail(`Expected '${key}' to be '${stringify(ek)}', got '${stringify(ak)}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1189,7 +1193,15 @@ Actual: ${stringify(fullActual)}`);
|
||||
locations && ts.sort(locations, (r1, r2) => ts.compareStringsCaseSensitive(r1.fileName, r2.fileName) || r1.textSpan.start - r2.textSpan.start);
|
||||
assert.deepEqual(sort(references), sort(ranges.map((rangeOrOptions): ts.RenameLocation => {
|
||||
const { range, ...prefixSuffixText } = "range" in rangeOrOptions ? rangeOrOptions : { range: rangeOrOptions };
|
||||
return { fileName: range.fileName, textSpan: ts.createTextSpanFromRange(range), ...prefixSuffixText };
|
||||
const { contextRangeIndex } = (range.marker && range.marker.data || {}) as { contextRangeIndex?: number; };
|
||||
return {
|
||||
fileName: range.fileName,
|
||||
textSpan: ts.createTextSpanFromRange(range),
|
||||
...(contextRangeIndex !== undefined ?
|
||||
{ contextSpan: ts.createTextSpanFromRange(this.getRanges()[contextRangeIndex]) } :
|
||||
undefined),
|
||||
...prefixSuffixText
|
||||
};
|
||||
})));
|
||||
}
|
||||
}
|
||||
@@ -1844,6 +1856,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
range.end = updatePosition(range.end, editStart, editEnd, newText);
|
||||
}
|
||||
}
|
||||
this.testData.rangesByText = undefined;
|
||||
}
|
||||
|
||||
private removeWhitespace(text: string): string {
|
||||
@@ -2026,7 +2039,9 @@ Actual: ${stringify(fullActual)}`);
|
||||
}
|
||||
|
||||
public rangesByText(): ts.Map<Range[]> {
|
||||
if (this.testData.rangesByText) return this.testData.rangesByText;
|
||||
const result = ts.createMultiMap<Range>();
|
||||
this.testData.rangesByText = result;
|
||||
for (const range of this.getRanges()) {
|
||||
const text = this.rangeText(range);
|
||||
result.add(text, range);
|
||||
@@ -2714,8 +2729,8 @@ Actual: ${stringify(fullActual)}`);
|
||||
return this.languageService.getDocumentHighlights(this.activeFile.fileName, this.currentCaretPosition, filesToSearch);
|
||||
}
|
||||
|
||||
public verifyRangesAreOccurrences(isWriteAccess?: boolean) {
|
||||
const ranges = this.getRanges();
|
||||
public verifyRangesAreOccurrences(isWriteAccess?: boolean, ranges?: Range[]) {
|
||||
ranges = ranges || this.getRanges();
|
||||
for (const r of ranges) {
|
||||
this.goToRangeStart(r);
|
||||
this.verifyOccurrencesAtPositionListCount(ranges.length);
|
||||
@@ -2725,8 +2740,13 @@ Actual: ${stringify(fullActual)}`);
|
||||
}
|
||||
}
|
||||
|
||||
public verifyRangesWithSameTextAreRenameLocations() {
|
||||
this.rangesByText().forEach(ranges => this.verifyRangesAreRenameLocations(ranges));
|
||||
public verifyRangesWithSameTextAreRenameLocations(...texts: string[]) {
|
||||
if (texts.length) {
|
||||
texts.forEach(text => this.verifyRangesAreRenameLocations(this.rangesByText().get(text)!));
|
||||
}
|
||||
else {
|
||||
this.rangesByText().forEach(ranges => this.verifyRangesAreRenameLocations(ranges));
|
||||
}
|
||||
}
|
||||
|
||||
public verifyRangesWithSameTextAreDocumentHighlights() {
|
||||
@@ -3971,7 +3991,7 @@ namespace FourSlashInterface {
|
||||
this.state.verifyGetReferencesForServerTest(expected);
|
||||
}
|
||||
|
||||
public singleReferenceGroup(definition: ReferenceGroupDefinition, ranges?: FourSlash.Range[]) {
|
||||
public singleReferenceGroup(definition: ReferenceGroupDefinition, ranges?: FourSlash.Range[] | string) {
|
||||
this.state.verifySingleReferenceGroup(definition, ranges);
|
||||
}
|
||||
|
||||
@@ -4093,12 +4113,12 @@ namespace FourSlashInterface {
|
||||
this.state.verifyOccurrencesAtPositionListCount(expectedCount);
|
||||
}
|
||||
|
||||
public rangesAreOccurrences(isWriteAccess?: boolean) {
|
||||
this.state.verifyRangesAreOccurrences(isWriteAccess);
|
||||
public rangesAreOccurrences(isWriteAccess?: boolean, ranges?: FourSlash.Range[]) {
|
||||
this.state.verifyRangesAreOccurrences(isWriteAccess, ranges);
|
||||
}
|
||||
|
||||
public rangesWithSameTextAreRenameLocations() {
|
||||
this.state.verifyRangesWithSameTextAreRenameLocations();
|
||||
public rangesWithSameTextAreRenameLocations(...texts: string[]) {
|
||||
this.state.verifyRangesWithSameTextAreRenameLocations(...texts);
|
||||
}
|
||||
|
||||
public rangesAreRenameLocations(options?: FourSlash.Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges?: FourSlash.Range[] }) {
|
||||
|
||||
Vendored
+2018
-1804
File diff suppressed because it is too large
Load Diff
Vendored
+94
-30
@@ -2,6 +2,10 @@
|
||||
/// DOM Iterable APIs
|
||||
/////////////////////////////
|
||||
|
||||
interface AudioParam {
|
||||
setValueCurveAtTime(values: Iterable<number>, startTime: number, duration: number): AudioParam;
|
||||
}
|
||||
|
||||
interface AudioParamMap extends ReadonlyMap<string, AudioParam> {
|
||||
}
|
||||
|
||||
@@ -9,6 +13,11 @@ interface AudioTrackList {
|
||||
[Symbol.iterator](): IterableIterator<AudioTrack>;
|
||||
}
|
||||
|
||||
interface BaseAudioContext {
|
||||
createIIRFilter(feedforward: Iterable<number>, feedback: Iterable<number>): IIRFilterNode;
|
||||
createPeriodicWave(real: Iterable<number>, imag: Iterable<number>, constraints?: PeriodicWaveConstraints): PeriodicWave;
|
||||
}
|
||||
|
||||
interface CSSRuleList {
|
||||
[Symbol.iterator](): IterableIterator<CSSRule>;
|
||||
}
|
||||
@@ -17,6 +26,14 @@ interface CSSStyleDeclaration {
|
||||
[Symbol.iterator](): IterableIterator<string>;
|
||||
}
|
||||
|
||||
interface Cache {
|
||||
addAll(requests: Iterable<RequestInfo>): Promise<void>;
|
||||
}
|
||||
|
||||
interface CanvasPathDrawingStyles {
|
||||
setLineDash(segments: Iterable<number>): void;
|
||||
}
|
||||
|
||||
interface ClientRectList {
|
||||
[Symbol.iterator](): IterableIterator<ClientRect>;
|
||||
}
|
||||
@@ -46,16 +63,16 @@ interface FileList {
|
||||
|
||||
interface FormData {
|
||||
[Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>;
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the list.
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the list.
|
||||
*/
|
||||
entries(): IterableIterator<[string, FormDataEntryValue]>;
|
||||
/**
|
||||
* Returns a list of keys in the list.
|
||||
/**
|
||||
* Returns a list of keys in the list.
|
||||
*/
|
||||
keys(): IterableIterator<string>;
|
||||
/**
|
||||
* Returns a list of values in the list.
|
||||
/**
|
||||
* Returns a list of values in the list.
|
||||
*/
|
||||
values(): IterableIterator<FormDataEntryValue>;
|
||||
}
|
||||
@@ -82,20 +99,29 @@ interface HTMLSelectElement {
|
||||
|
||||
interface Headers {
|
||||
[Symbol.iterator](): IterableIterator<[string, string]>;
|
||||
/**
|
||||
* Returns an iterator allowing to go through all key/value pairs contained in this object.
|
||||
/**
|
||||
* Returns an iterator allowing to go through all key/value pairs contained in this object.
|
||||
*/
|
||||
entries(): IterableIterator<[string, string]>;
|
||||
/**
|
||||
* Returns an iterator allowing to go through all keys of the key/value pairs contained in this object.
|
||||
/**
|
||||
* Returns an iterator allowing to go through all keys of the key/value pairs contained in this object.
|
||||
*/
|
||||
keys(): IterableIterator<string>;
|
||||
/**
|
||||
* Returns an iterator allowing to go through all values of the key/value pairs contained in this object.
|
||||
/**
|
||||
* Returns an iterator allowing to go through all values of the key/value pairs contained in this object.
|
||||
*/
|
||||
values(): IterableIterator<string>;
|
||||
}
|
||||
|
||||
interface IDBObjectStore {
|
||||
/**
|
||||
* Creates a new index in store with the given name, keyPath and options and returns a new IDBIndex. If the keyPath and options define constraints that cannot be satisfied with the data already in store the upgrade transaction will abort with a "ConstraintError" DOMException.
|
||||
*
|
||||
* Throws an "InvalidStateError" DOMException if not called within an upgrade transaction.
|
||||
*/
|
||||
createIndex(name: string, keyPath: string | Iterable<string>, options?: IDBIndexParameters): IDBIndex;
|
||||
}
|
||||
|
||||
interface MediaKeyStatusMap {
|
||||
[Symbol.iterator](): IterableIterator<[BufferSource, MediaKeyStatus]>;
|
||||
entries(): IterableIterator<[BufferSource, MediaKeyStatus]>;
|
||||
@@ -115,34 +141,38 @@ interface NamedNodeMap {
|
||||
[Symbol.iterator](): IterableIterator<Attr>;
|
||||
}
|
||||
|
||||
interface Navigator {
|
||||
requestMediaKeySystemAccess(keySystem: string, supportedConfigurations: Iterable<MediaKeySystemConfiguration>): Promise<MediaKeySystemAccess>;
|
||||
}
|
||||
|
||||
interface NodeList {
|
||||
[Symbol.iterator](): IterableIterator<Node>;
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the list.
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the list.
|
||||
*/
|
||||
entries(): IterableIterator<[number, Node]>;
|
||||
/**
|
||||
* Returns an list of keys in the list.
|
||||
/**
|
||||
* Returns an list of keys in the list.
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
/**
|
||||
* Returns an list of values in the list.
|
||||
/**
|
||||
* Returns an list of values in the list.
|
||||
*/
|
||||
values(): IterableIterator<Node>;
|
||||
}
|
||||
|
||||
interface NodeListOf<TNode extends Node> {
|
||||
[Symbol.iterator](): IterableIterator<TNode>;
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the list.
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the list.
|
||||
*/
|
||||
entries(): IterableIterator<[number, TNode]>;
|
||||
/**
|
||||
* Returns an list of keys in the list.
|
||||
/**
|
||||
* Returns an list of keys in the list.
|
||||
*/
|
||||
keys(): IterableIterator<number>;
|
||||
/**
|
||||
* Returns an list of values in the list.
|
||||
/**
|
||||
* Returns an list of values in the list.
|
||||
*/
|
||||
values(): IterableIterator<TNode>;
|
||||
}
|
||||
@@ -155,6 +185,10 @@ interface PluginArray {
|
||||
[Symbol.iterator](): IterableIterator<Plugin>;
|
||||
}
|
||||
|
||||
interface RTCRtpTransceiver {
|
||||
setCodecPreferences(codecs: Iterable<RTCRtpCodecCapability>): void;
|
||||
}
|
||||
|
||||
interface RTCStatsReport extends ReadonlyMap<string, any> {
|
||||
}
|
||||
|
||||
@@ -208,20 +242,50 @@ interface TouchList {
|
||||
|
||||
interface URLSearchParams {
|
||||
[Symbol.iterator](): IterableIterator<[string, string]>;
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the search params.
|
||||
/**
|
||||
* Returns an array of key, value pairs for every entry in the search params.
|
||||
*/
|
||||
entries(): IterableIterator<[string, string]>;
|
||||
/**
|
||||
* Returns a list of keys in the search params.
|
||||
/**
|
||||
* Returns a list of keys in the search params.
|
||||
*/
|
||||
keys(): IterableIterator<string>;
|
||||
/**
|
||||
* Returns a list of values in the search params.
|
||||
/**
|
||||
* Returns a list of values in the search params.
|
||||
*/
|
||||
values(): IterableIterator<string>;
|
||||
}
|
||||
|
||||
interface VRDisplay {
|
||||
requestPresent(layers: Iterable<VRLayer>): Promise<void>;
|
||||
}
|
||||
|
||||
interface VideoTrackList {
|
||||
[Symbol.iterator](): IterableIterator<VideoTrack>;
|
||||
}
|
||||
|
||||
interface WEBGL_draw_buffers {
|
||||
drawBuffersWEBGL(buffers: Iterable<GLenum>): void;
|
||||
}
|
||||
|
||||
interface WebAuthentication {
|
||||
makeCredential(accountInformation: Account, cryptoParameters: Iterable<ScopedCredentialParameters>, attestationChallenge: Int8Array | Int16Array | Int32Array | Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array | DataView | ArrayBuffer | null, options?: ScopedCredentialOptions): Promise<ScopedCredentialInfo>;
|
||||
}
|
||||
|
||||
interface WebGLRenderingContextBase {
|
||||
uniform1fv(location: WebGLUniformLocation | null, v: Iterable<GLfloat>): void;
|
||||
uniform2fv(location: WebGLUniformLocation | null, v: Iterable<GLfloat>): void;
|
||||
uniform3fv(location: WebGLUniformLocation | null, v: Iterable<GLfloat>): void;
|
||||
uniform4fv(location: WebGLUniformLocation | null, v: Iterable<GLfloat>): void;
|
||||
uniform1iv(location: WebGLUniformLocation | null, v: Iterable<GLint>): void;
|
||||
uniform2iv(location: WebGLUniformLocation | null, v: Iterable<GLint>): void;
|
||||
uniform3iv(location: WebGLUniformLocation | null, v: Iterable<GLint>): void;
|
||||
uniform4iv(location: WebGLUniformLocation | null, v: Iterable<GLint>): void;
|
||||
uniformMatrix2fv(location: WebGLUniformLocation | null, transpose: GLboolean, value: Iterable<GLfloat>): void;
|
||||
uniformMatrix3fv(location: WebGLUniformLocation | null, transpose: GLboolean, value: Iterable<GLfloat>): void;
|
||||
uniformMatrix4fv(location: WebGLUniformLocation | null, transpose: GLboolean, value: Iterable<GLfloat>): void;
|
||||
vertexAttrib1fv(index: GLuint, values: Iterable<GLfloat>): void;
|
||||
vertexAttrib2fv(index: GLuint, values: Iterable<GLfloat>): void;
|
||||
vertexAttrib3fv(index: GLuint, values: Iterable<GLfloat>): void;
|
||||
vertexAttrib4fv(index: GLuint, values: Iterable<GLfloat>): void;
|
||||
}
|
||||
|
||||
Vendored
+395
-319
File diff suppressed because it is too large
Load Diff
+16
-8
@@ -872,8 +872,16 @@ namespace ts.server.protocol {
|
||||
file: string;
|
||||
}
|
||||
|
||||
export interface TextSpanWithContext extends TextSpan {
|
||||
contextStart?: Location;
|
||||
contextEnd?: Location;
|
||||
}
|
||||
|
||||
export interface FileSpanWithContext extends FileSpan, TextSpanWithContext {
|
||||
}
|
||||
|
||||
export interface DefinitionInfoAndBoundSpan {
|
||||
definitions: ReadonlyArray<FileSpan>;
|
||||
definitions: ReadonlyArray<FileSpanWithContext>;
|
||||
textSpan: TextSpan;
|
||||
}
|
||||
|
||||
@@ -881,7 +889,7 @@ namespace ts.server.protocol {
|
||||
* Definition response message. Gives text range for definition.
|
||||
*/
|
||||
export interface DefinitionResponse extends Response {
|
||||
body?: FileSpan[];
|
||||
body?: FileSpanWithContext[];
|
||||
}
|
||||
|
||||
export interface DefinitionInfoAndBoundSpanReponse extends Response {
|
||||
@@ -892,14 +900,14 @@ namespace ts.server.protocol {
|
||||
* Definition response message. Gives text range for definition.
|
||||
*/
|
||||
export interface TypeDefinitionResponse extends Response {
|
||||
body?: FileSpan[];
|
||||
body?: FileSpanWithContext[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation response message. Gives text range for implementations.
|
||||
*/
|
||||
export interface ImplementationResponse extends Response {
|
||||
body?: FileSpan[];
|
||||
body?: FileSpanWithContext[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -942,7 +950,7 @@ namespace ts.server.protocol {
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
export interface OccurrencesResponseItem extends FileSpan {
|
||||
export interface OccurrencesResponseItem extends FileSpanWithContext {
|
||||
/**
|
||||
* True if the occurrence is a write location, false otherwise.
|
||||
*/
|
||||
@@ -972,7 +980,7 @@ namespace ts.server.protocol {
|
||||
/**
|
||||
* Span augmented with extra information that denotes the kind of the highlighting to be used for span.
|
||||
*/
|
||||
export interface HighlightSpan extends TextSpan {
|
||||
export interface HighlightSpan extends TextSpanWithContext {
|
||||
kind: HighlightSpanKind;
|
||||
}
|
||||
|
||||
@@ -1007,7 +1015,7 @@ namespace ts.server.protocol {
|
||||
command: CommandTypes.References;
|
||||
}
|
||||
|
||||
export interface ReferencesResponseItem extends FileSpan {
|
||||
export interface ReferencesResponseItem extends FileSpanWithContext {
|
||||
/** Text of line containing the reference. Including this
|
||||
* with the response avoids latency of editor loading files
|
||||
* to show text of reference line (the server already has
|
||||
@@ -1150,7 +1158,7 @@ namespace ts.server.protocol {
|
||||
locs: RenameTextSpan[];
|
||||
}
|
||||
|
||||
export interface RenameTextSpan extends TextSpan {
|
||||
export interface RenameTextSpan extends TextSpanWithContext {
|
||||
readonly prefixText?: string;
|
||||
readonly suffixText?: string;
|
||||
}
|
||||
|
||||
+136
-125
@@ -354,13 +354,17 @@ namespace ts.server {
|
||||
defaultProject,
|
||||
initialLocation,
|
||||
({ project, location }, getMappedLocation) => {
|
||||
for (const outputReferencedSymbol of project.getLanguageService().findReferences(location.fileName, location.pos) || emptyArray) {
|
||||
for (const outputReferencedSymbol of project.getLanguageService().findReferences(location.fileName, location.pos) || emptyArray) {
|
||||
const mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(outputReferencedSymbol.definition));
|
||||
const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? outputReferencedSymbol.definition : {
|
||||
...outputReferencedSymbol.definition,
|
||||
textSpan: createTextSpan(mappedDefinitionFile.pos, outputReferencedSymbol.definition.textSpan.length),
|
||||
fileName: mappedDefinitionFile.fileName,
|
||||
};
|
||||
const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ?
|
||||
outputReferencedSymbol.definition :
|
||||
{
|
||||
...outputReferencedSymbol.definition,
|
||||
textSpan: createTextSpan(mappedDefinitionFile.pos, outputReferencedSymbol.definition.textSpan.length),
|
||||
fileName: mappedDefinitionFile.fileName,
|
||||
contextSpan: getMappedContextSpan(outputReferencedSymbol.definition, project)
|
||||
};
|
||||
|
||||
let symbolToAddTo = find(outputs, o => documentSpansEqual(o.definition, definition));
|
||||
if (!symbolToAddTo) {
|
||||
symbolToAddTo = { definition, references: [] };
|
||||
@@ -481,9 +485,39 @@ namespace ts.server {
|
||||
return { fileName, pos: textSpan.start };
|
||||
}
|
||||
|
||||
function getMappedLocation(location: DocumentPosition, projectService: ProjectService, project: Project): DocumentPosition | undefined {
|
||||
function getMappedLocation(location: DocumentPosition, project: Project): DocumentPosition | undefined {
|
||||
const mapsTo = project.getSourceMapper().tryGetSourcePosition(location);
|
||||
return mapsTo && projectService.fileExists(toNormalizedPath(mapsTo.fileName)) ? mapsTo : undefined;
|
||||
return mapsTo && project.projectService.fileExists(toNormalizedPath(mapsTo.fileName)) ? mapsTo : undefined;
|
||||
}
|
||||
|
||||
function getMappedDocumentSpan(documentSpan: DocumentSpan, project: Project): DocumentSpan | undefined {
|
||||
const newPosition = getMappedLocation(documentSpanLocation(documentSpan), project);
|
||||
if (!newPosition) return undefined;
|
||||
return {
|
||||
fileName: newPosition.fileName,
|
||||
textSpan: {
|
||||
start: newPosition.pos,
|
||||
length: documentSpan.textSpan.length
|
||||
},
|
||||
originalFileName: documentSpan.fileName,
|
||||
originalTextSpan: documentSpan.textSpan,
|
||||
contextSpan: getMappedContextSpan(documentSpan, project),
|
||||
originalContextSpan: documentSpan.contextSpan
|
||||
};
|
||||
}
|
||||
|
||||
function getMappedContextSpan(documentSpan: DocumentSpan, project: Project): TextSpan | undefined {
|
||||
const contextSpanStart = documentSpan.contextSpan && getMappedLocation(
|
||||
{ fileName: documentSpan.fileName, pos: documentSpan.contextSpan.start },
|
||||
project
|
||||
);
|
||||
const contextSpanEnd = documentSpan.contextSpan && getMappedLocation(
|
||||
{ fileName: documentSpan.fileName, pos: documentSpan.contextSpan.start + documentSpan.contextSpan.length },
|
||||
project
|
||||
);
|
||||
return contextSpanStart && contextSpanEnd ?
|
||||
{ start: contextSpanStart.pos, length: contextSpanEnd.pos - contextSpanStart.pos } :
|
||||
undefined;
|
||||
}
|
||||
|
||||
export interface SessionOptions {
|
||||
@@ -937,7 +971,7 @@ namespace ts.server {
|
||||
: diagnostics.map(d => formatDiag(file, project, d));
|
||||
}
|
||||
|
||||
private getDefinition(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.FileSpan> | ReadonlyArray<DefinitionInfo> {
|
||||
private getDefinition(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.FileSpanWithContext> | ReadonlyArray<DefinitionInfo> {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
const definitions = this.mapDefinitionInfoLocations(project.getLanguageService().getDefinitionAtPosition(file, position) || emptyArray, project);
|
||||
@@ -946,19 +980,13 @@ namespace ts.server {
|
||||
|
||||
private mapDefinitionInfoLocations(definitions: ReadonlyArray<DefinitionInfo>, project: Project): ReadonlyArray<DefinitionInfo> {
|
||||
return definitions.map((info): DefinitionInfo => {
|
||||
const newLoc = getMappedLocation(documentSpanLocation(info), this.projectService, project);
|
||||
return !newLoc ? info : {
|
||||
const newDocumentSpan = getMappedDocumentSpan(info, project);
|
||||
return !newDocumentSpan ? info : {
|
||||
...newDocumentSpan,
|
||||
containerKind: info.containerKind,
|
||||
containerName: info.containerName,
|
||||
fileName: newLoc.fileName,
|
||||
kind: info.kind,
|
||||
name: info.name,
|
||||
textSpan: {
|
||||
start: newLoc.pos,
|
||||
length: info.textSpan.length
|
||||
},
|
||||
originalFileName: info.fileName,
|
||||
originalTextSpan: info.textSpan,
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -983,7 +1011,7 @@ namespace ts.server {
|
||||
if (simplifiedResult) {
|
||||
return {
|
||||
definitions: this.mapDefinitionInfo(definitions, project),
|
||||
textSpan: this.toLocationTextSpan(textSpan, scriptInfo)
|
||||
textSpan: toProcolTextSpan(textSpan, scriptInfo)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -998,8 +1026,8 @@ namespace ts.server {
|
||||
return project.getLanguageService().getEmitOutput(file);
|
||||
}
|
||||
|
||||
private mapDefinitionInfo(definitions: ReadonlyArray<DefinitionInfo>, project: Project): ReadonlyArray<protocol.FileSpan> {
|
||||
return definitions.map(def => this.toFileSpan(def.fileName, def.textSpan, project));
|
||||
private mapDefinitionInfo(definitions: ReadonlyArray<DefinitionInfo>, project: Project): ReadonlyArray<protocol.FileSpanWithContext> {
|
||||
return definitions.map(def => this.toFileSpanWithContext(def.fileName, def.textSpan, def.contextSpan, project));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1017,7 +1045,9 @@ namespace ts.server {
|
||||
fileName: def.originalFileName,
|
||||
textSpan: def.originalTextSpan,
|
||||
targetFileName: def.fileName,
|
||||
targetTextSpan: def.textSpan
|
||||
targetTextSpan: def.textSpan,
|
||||
contextSpan: def.originalContextSpan,
|
||||
targetContextSpan: def.contextSpan
|
||||
};
|
||||
}
|
||||
return def;
|
||||
@@ -1035,7 +1065,15 @@ namespace ts.server {
|
||||
};
|
||||
}
|
||||
|
||||
private getTypeDefinition(args: protocol.FileLocationRequestArgs): ReadonlyArray<protocol.FileSpan> {
|
||||
private toFileSpanWithContext(fileName: string, textSpan: TextSpan, contextSpan: TextSpan | undefined, project: Project): protocol.FileSpanWithContext {
|
||||
const fileSpan = this.toFileSpan(fileName, textSpan, project);
|
||||
const context = contextSpan && this.toFileSpan(fileName, contextSpan, project);
|
||||
return context ?
|
||||
{ ...fileSpan, contextStart: context.start, contextEnd: context.end } :
|
||||
fileSpan;
|
||||
}
|
||||
|
||||
private getTypeDefinition(args: protocol.FileLocationRequestArgs): ReadonlyArray<protocol.FileSpanWithContext> {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
|
||||
@@ -1045,58 +1083,40 @@ namespace ts.server {
|
||||
|
||||
private mapImplementationLocations(implementations: ReadonlyArray<ImplementationLocation>, project: Project): ReadonlyArray<ImplementationLocation> {
|
||||
return implementations.map((info): ImplementationLocation => {
|
||||
const newLoc = getMappedLocation(documentSpanLocation(info), this.projectService, project);
|
||||
return !newLoc ? info : {
|
||||
fileName: newLoc.fileName,
|
||||
const newDocumentSpan = getMappedDocumentSpan(info, project);
|
||||
return !newDocumentSpan ? info : {
|
||||
...newDocumentSpan,
|
||||
kind: info.kind,
|
||||
displayParts: info.displayParts,
|
||||
textSpan: {
|
||||
start: newLoc.pos,
|
||||
length: info.textSpan.length
|
||||
},
|
||||
originalFileName: info.fileName,
|
||||
originalTextSpan: info.textSpan,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private getImplementation(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.FileSpan> | ReadonlyArray<ImplementationLocation> {
|
||||
private getImplementation(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.FileSpanWithContext> | ReadonlyArray<ImplementationLocation> {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
const implementations = this.mapImplementationLocations(project.getLanguageService().getImplementationAtPosition(file, position) || emptyArray, project);
|
||||
if (simplifiedResult) {
|
||||
return implementations.map(({ fileName, textSpan }) => this.toFileSpan(fileName, textSpan, project));
|
||||
}
|
||||
|
||||
return implementations.map(Session.mapToOriginalLocation);
|
||||
return simplifiedResult ?
|
||||
implementations.map(({ fileName, textSpan, contextSpan }) => this.toFileSpanWithContext(fileName, textSpan, contextSpan, project)) :
|
||||
implementations.map(Session.mapToOriginalLocation);
|
||||
}
|
||||
|
||||
private getOccurrences(args: protocol.FileLocationRequestArgs): ReadonlyArray<protocol.OccurrencesResponseItem> {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
|
||||
const position = this.getPositionInFile(args, file);
|
||||
|
||||
const occurrences = project.getLanguageService().getOccurrencesAtPosition(file, position);
|
||||
|
||||
if (!occurrences) {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
return occurrences.map(occurrence => {
|
||||
const { fileName, isWriteAccess, textSpan, isInString } = occurrence;
|
||||
const scriptInfo = project.getScriptInfo(fileName)!;
|
||||
const result: protocol.OccurrencesResponseItem = {
|
||||
start: scriptInfo.positionToLineOffset(textSpan.start),
|
||||
end: scriptInfo.positionToLineOffset(textSpanEnd(textSpan)),
|
||||
file: fileName,
|
||||
isWriteAccess,
|
||||
};
|
||||
// no need to serialize the property if it is not true
|
||||
if (isInString) {
|
||||
result.isInString = isInString;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
return occurrences ?
|
||||
occurrences.map<protocol.OccurrencesResponseItem>(occurrence => {
|
||||
const { fileName, isWriteAccess, textSpan, isInString, contextSpan } = occurrence;
|
||||
const scriptInfo = project.getScriptInfo(fileName)!;
|
||||
return {
|
||||
...toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo),
|
||||
file: fileName,
|
||||
isWriteAccess,
|
||||
...(isInString ? { isInString } : undefined)
|
||||
};
|
||||
}) :
|
||||
emptyArray;
|
||||
}
|
||||
|
||||
private getSyntacticDiagnosticsSync(args: protocol.SyntacticDiagnosticsSyncRequestArgs): ReadonlyArray<protocol.Diagnostic> | ReadonlyArray<protocol.DiagnosticWithLinePosition> {
|
||||
@@ -1139,33 +1159,19 @@ namespace ts.server {
|
||||
const position = this.getPositionInFile(args, file);
|
||||
const documentHighlights = project.getLanguageService().getDocumentHighlights(file, position, args.filesToSearch);
|
||||
|
||||
if (!documentHighlights) {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
if (simplifiedResult) {
|
||||
return documentHighlights.map(convertToDocumentHighlightsItem);
|
||||
}
|
||||
else {
|
||||
return documentHighlights;
|
||||
}
|
||||
|
||||
function convertToDocumentHighlightsItem(documentHighlights: DocumentHighlights): protocol.DocumentHighlightsItem {
|
||||
const { fileName, highlightSpans } = documentHighlights;
|
||||
if (!documentHighlights) return emptyArray;
|
||||
if (!simplifiedResult) return documentHighlights;
|
||||
|
||||
return documentHighlights.map<protocol.DocumentHighlightsItem>(({ fileName, highlightSpans }) => {
|
||||
const scriptInfo = project.getScriptInfo(fileName)!;
|
||||
return {
|
||||
file: fileName,
|
||||
highlightSpans: highlightSpans.map(convertHighlightSpan)
|
||||
highlightSpans: highlightSpans.map(({ textSpan, kind, contextSpan }) => ({
|
||||
...toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo),
|
||||
kind
|
||||
}))
|
||||
};
|
||||
|
||||
function convertHighlightSpan(highlightSpan: HighlightSpan): protocol.HighlightSpan {
|
||||
const { textSpan, kind } = highlightSpan;
|
||||
const start = scriptInfo.positionToLineOffset(textSpan.start);
|
||||
const end = scriptInfo.positionToLineOffset(textSpanEnd(textSpan));
|
||||
return { start, end, kind };
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private setCompilerOptionsForInferredProjects(args: protocol.SetCompilerOptionsForInferredProjectsArgs): void {
|
||||
@@ -1258,7 +1264,7 @@ namespace ts.server {
|
||||
if (info.canRename) {
|
||||
const { canRename, fileToRename, displayName, fullDisplayName, kind, kindModifiers, triggerSpan } = info;
|
||||
return identity<protocol.RenameInfoSuccess>(
|
||||
{ canRename, fileToRename, displayName, fullDisplayName, kind, kindModifiers, triggerSpan: this.toLocationTextSpan(triggerSpan, scriptInfo) });
|
||||
{ canRename, fileToRename, displayName, fullDisplayName, kind, kindModifiers, triggerSpan: toProcolTextSpan(triggerSpan, scriptInfo) });
|
||||
}
|
||||
else {
|
||||
return info;
|
||||
@@ -1267,11 +1273,11 @@ namespace ts.server {
|
||||
|
||||
private toSpanGroups(locations: ReadonlyArray<RenameLocation>): ReadonlyArray<protocol.SpanGroup> {
|
||||
const map = createMap<protocol.SpanGroup>();
|
||||
for (const { fileName, textSpan, originalTextSpan: _, originalFileName: _1, ...prefixSuffixText } of locations) {
|
||||
for (const { fileName, textSpan, contextSpan, originalContextSpan: _2, originalTextSpan: _, originalFileName: _1, ...prefixSuffixText } of locations) {
|
||||
let group = map.get(fileName);
|
||||
if (!group) map.set(fileName, group = { file: fileName, locs: [] });
|
||||
const scriptInfo = Debug.assertDefined(this.projectService.getScriptInfo(fileName));
|
||||
group.locs.push({ ...this.toLocationTextSpan(textSpan, scriptInfo), ...prefixSuffixText });
|
||||
group.locs.push({ ...toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo), ...prefixSuffixText });
|
||||
}
|
||||
return arrayFrom(map.values());
|
||||
}
|
||||
@@ -1286,30 +1292,31 @@ namespace ts.server {
|
||||
{ fileName: args.file, pos: position },
|
||||
);
|
||||
|
||||
if (simplifiedResult) {
|
||||
const defaultProject = this.getDefaultProject(args);
|
||||
const scriptInfo = defaultProject.getScriptInfoForNormalizedPath(file)!;
|
||||
const nameInfo = defaultProject.getLanguageService().getQuickInfoAtPosition(file, position);
|
||||
const symbolDisplayString = nameInfo ? displayPartsToString(nameInfo.displayParts) : "";
|
||||
const nameSpan = nameInfo && nameInfo.textSpan;
|
||||
const symbolStartOffset = nameSpan ? scriptInfo.positionToLineOffset(nameSpan.start).offset : 0;
|
||||
const symbolName = nameSpan ? scriptInfo.getSnapshot().getText(nameSpan.start, textSpanEnd(nameSpan)) : "";
|
||||
const refs: ReadonlyArray<protocol.ReferencesResponseItem> = flatMap(references, referencedSymbol =>
|
||||
referencedSymbol.references.map(({ fileName, textSpan, isWriteAccess, isDefinition }): protocol.ReferencesResponseItem => {
|
||||
const scriptInfo = Debug.assertDefined(this.projectService.getScriptInfo(fileName));
|
||||
const start = scriptInfo.positionToLineOffset(textSpan.start);
|
||||
const lineSpan = scriptInfo.lineToTextSpan(start.line - 1);
|
||||
const lineText = scriptInfo.getSnapshot().getText(lineSpan.start, textSpanEnd(lineSpan)).replace(/\r|\n/g, "");
|
||||
return { ...toFileSpan(fileName, textSpan, scriptInfo), lineText, isWriteAccess, isDefinition };
|
||||
}));
|
||||
const result: protocol.ReferencesResponseBody = { refs, symbolName, symbolStartOffset, symbolDisplayString };
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return references;
|
||||
}
|
||||
}
|
||||
if (!simplifiedResult) return references;
|
||||
|
||||
const defaultProject = this.getDefaultProject(args);
|
||||
const scriptInfo = defaultProject.getScriptInfoForNormalizedPath(file)!;
|
||||
const nameInfo = defaultProject.getLanguageService().getQuickInfoAtPosition(file, position);
|
||||
const symbolDisplayString = nameInfo ? displayPartsToString(nameInfo.displayParts) : "";
|
||||
const nameSpan = nameInfo && nameInfo.textSpan;
|
||||
const symbolStartOffset = nameSpan ? scriptInfo.positionToLineOffset(nameSpan.start).offset : 0;
|
||||
const symbolName = nameSpan ? scriptInfo.getSnapshot().getText(nameSpan.start, textSpanEnd(nameSpan)) : "";
|
||||
const refs: ReadonlyArray<protocol.ReferencesResponseItem> = flatMap(references, referencedSymbol =>
|
||||
referencedSymbol.references.map(({ fileName, textSpan, contextSpan, isWriteAccess, isDefinition }): protocol.ReferencesResponseItem => {
|
||||
const scriptInfo = Debug.assertDefined(this.projectService.getScriptInfo(fileName));
|
||||
const span = toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo);
|
||||
const lineSpan = scriptInfo.lineToTextSpan(span.start.line - 1);
|
||||
const lineText = scriptInfo.getSnapshot().getText(lineSpan.start, textSpanEnd(lineSpan)).replace(/\r|\n/g, "");
|
||||
return {
|
||||
file: fileName,
|
||||
...span,
|
||||
lineText,
|
||||
isWriteAccess,
|
||||
isDefinition
|
||||
};
|
||||
}));
|
||||
return { refs, symbolName, symbolStartOffset, symbolDisplayString };
|
||||
}
|
||||
/**
|
||||
* @param fileName is the name of the file to be opened
|
||||
* @param fileContent is a version of the file content that is known to be more up to date than the one on disk
|
||||
@@ -1357,8 +1364,8 @@ namespace ts.server {
|
||||
if (simplifiedResult) {
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
return spans.map(s => ({
|
||||
textSpan: this.toLocationTextSpan(s.textSpan, scriptInfo),
|
||||
hintSpan: this.toLocationTextSpan(s.hintSpan, scriptInfo),
|
||||
textSpan: toProcolTextSpan(s.textSpan, scriptInfo),
|
||||
hintSpan: toProcolTextSpan(s.hintSpan, scriptInfo),
|
||||
bannerText: s.bannerText,
|
||||
autoCollapse: s.autoCollapse,
|
||||
kind: s.kind
|
||||
@@ -1547,7 +1554,7 @@ namespace ts.server {
|
||||
const entries = mapDefined<CompletionEntry, protocol.CompletionEntry>(completions.entries, entry => {
|
||||
if (completions.isMemberCompletion || startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) {
|
||||
const { name, kind, kindModifiers, sortText, insertText, replacementSpan, hasAction, source, isRecommended } = entry;
|
||||
const convertedSpan = replacementSpan ? this.toLocationTextSpan(replacementSpan, scriptInfo) : undefined;
|
||||
const convertedSpan = replacementSpan ? toProcolTextSpan(replacementSpan, scriptInfo) : undefined;
|
||||
// Use `hasAction || undefined` to avoid serializing `false`.
|
||||
return { name, kind, kindModifiers, sortText, insertText, replacementSpan: convertedSpan, hasAction: hasAction || undefined, source, isRecommended };
|
||||
}
|
||||
@@ -1710,7 +1717,7 @@ namespace ts.server {
|
||||
text: item.text,
|
||||
kind: item.kind,
|
||||
kindModifiers: item.kindModifiers,
|
||||
spans: item.spans.map(span => this.toLocationTextSpan(span, scriptInfo)),
|
||||
spans: item.spans.map(span => toProcolTextSpan(span, scriptInfo)),
|
||||
childItems: this.mapLocationNavigationBarItems(item.childItems, scriptInfo),
|
||||
indent: item.indent
|
||||
}));
|
||||
@@ -1731,19 +1738,12 @@ namespace ts.server {
|
||||
text: tree.text,
|
||||
kind: tree.kind,
|
||||
kindModifiers: tree.kindModifiers,
|
||||
spans: tree.spans.map(span => this.toLocationTextSpan(span, scriptInfo)),
|
||||
nameSpan: tree.nameSpan && this.toLocationTextSpan(tree.nameSpan, scriptInfo),
|
||||
spans: tree.spans.map(span => toProcolTextSpan(span, scriptInfo)),
|
||||
nameSpan: tree.nameSpan && toProcolTextSpan(tree.nameSpan, scriptInfo),
|
||||
childItems: map(tree.childItems, item => this.toLocationNavigationTree(item, scriptInfo))
|
||||
};
|
||||
}
|
||||
|
||||
private toLocationTextSpan(span: TextSpan, scriptInfo: ScriptInfo): protocol.TextSpan {
|
||||
return {
|
||||
start: scriptInfo.positionToLineOffset(span.start),
|
||||
end: scriptInfo.positionToLineOffset(textSpanEnd(span))
|
||||
};
|
||||
}
|
||||
|
||||
private getNavigationTree(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationTree | NavigationTree | undefined {
|
||||
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
|
||||
const tree = languageService.getNavigationTree(file);
|
||||
@@ -2001,7 +2001,7 @@ namespace ts.server {
|
||||
return !spans
|
||||
? undefined
|
||||
: simplifiedResult
|
||||
? spans.map(span => this.toLocationTextSpan(span, scriptInfo))
|
||||
? spans.map(span => toProcolTextSpan(span, scriptInfo))
|
||||
: spans;
|
||||
}
|
||||
|
||||
@@ -2073,7 +2073,7 @@ namespace ts.server {
|
||||
|
||||
private mapSelectionRange(selectionRange: SelectionRange, scriptInfo: ScriptInfo): protocol.SelectionRange {
|
||||
const result: protocol.SelectionRange = {
|
||||
textSpan: this.toLocationTextSpan(selectionRange.textSpan, scriptInfo),
|
||||
textSpan: toProcolTextSpan(selectionRange.textSpan, scriptInfo),
|
||||
};
|
||||
if (selectionRange.parent) {
|
||||
result.parent = this.mapSelectionRange(selectionRange.parent, scriptInfo);
|
||||
@@ -2558,8 +2558,19 @@ namespace ts.server {
|
||||
readonly project: Project;
|
||||
}
|
||||
|
||||
function toFileSpan(fileName: string, textSpan: TextSpan, scriptInfo: ScriptInfo): protocol.FileSpan {
|
||||
return { file: fileName, start: scriptInfo.positionToLineOffset(textSpan.start), end: scriptInfo.positionToLineOffset(textSpanEnd(textSpan)) };
|
||||
function toProcolTextSpan(textSpan: TextSpan, scriptInfo: ScriptInfo): protocol.TextSpan {
|
||||
return {
|
||||
start: scriptInfo.positionToLineOffset(textSpan.start),
|
||||
end: scriptInfo.positionToLineOffset(textSpanEnd(textSpan))
|
||||
};
|
||||
}
|
||||
|
||||
function toProtocolTextSpanWithContext(span: TextSpan, contextSpan: TextSpan | undefined, scriptInfo: ScriptInfo): protocol.TextSpanWithContext {
|
||||
const textSpan = toProcolTextSpan(span, scriptInfo);
|
||||
const contextTextSpan = contextSpan && toProcolTextSpan(contextSpan, scriptInfo);
|
||||
return contextTextSpan ?
|
||||
{ ...textSpan, contextStart: contextTextSpan.start, contextEnd: contextTextSpan.end } :
|
||||
textSpan;
|
||||
}
|
||||
|
||||
function convertTextChangeToCodeEdit(change: TextChange, scriptInfo: ScriptInfoOrConfig): protocol.CodeEdit {
|
||||
|
||||
@@ -42,6 +42,9 @@ namespace ts.codefix {
|
||||
|
||||
// Property declarations
|
||||
Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code,
|
||||
|
||||
// Function expressions and declarations
|
||||
Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation.code,
|
||||
];
|
||||
registerCodeFix({
|
||||
errorCodes,
|
||||
@@ -73,6 +76,8 @@ namespace ts.codefix {
|
||||
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
|
||||
case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code:
|
||||
return Diagnostics.Infer_parameter_types_from_usage;
|
||||
case Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation.code:
|
||||
return Diagnostics.Infer_this_type_of_0_from_usage;
|
||||
default:
|
||||
return Diagnostics.Infer_type_of_0_from_usage;
|
||||
}
|
||||
@@ -176,6 +181,14 @@ namespace ts.codefix {
|
||||
}
|
||||
return undefined;
|
||||
|
||||
// Function 'this'
|
||||
case Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation.code:
|
||||
if (textChanges.isThisTypeAnnotatable(containingFunction) && markSeen(containingFunction)) {
|
||||
annotateThis(changes, sourceFile, containingFunction, program, host, cancellationToken);
|
||||
return containingFunction;
|
||||
}
|
||||
return undefined;
|
||||
|
||||
default:
|
||||
return Debug.fail(String(errorCode));
|
||||
}
|
||||
@@ -191,7 +204,9 @@ namespace ts.codefix {
|
||||
if (!isIdentifier(parameterDeclaration.name)) {
|
||||
return;
|
||||
}
|
||||
const parameterInferences = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) ||
|
||||
|
||||
const references = inferFunctionReferencesFromUsage(containingFunction, sourceFile, program, cancellationToken);
|
||||
const parameterInferences = InferFromReference.inferTypeForParametersFromReferences(references, containingFunction, program, cancellationToken) ||
|
||||
containingFunction.parameters.map<ParameterInference>(p => ({
|
||||
declaration: p,
|
||||
type: isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : program.getTypeChecker().getAnyType()
|
||||
@@ -213,6 +228,36 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function annotateThis(changes: textChanges.ChangeTracker, sourceFile: SourceFile, containingFunction: textChanges.ThisTypeAnnotatable, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken) {
|
||||
const references = inferFunctionReferencesFromUsage(containingFunction, sourceFile, program, cancellationToken);
|
||||
if (!references) {
|
||||
return;
|
||||
}
|
||||
|
||||
const thisInference = InferFromReference.inferTypeForThisFromReferences(references, program, cancellationToken);
|
||||
if (!thisInference) {
|
||||
return;
|
||||
}
|
||||
|
||||
const typeNode = getTypeNodeIfAccessible(thisInference, containingFunction, program, host);
|
||||
if (!typeNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInJSFile(containingFunction)) {
|
||||
annotateJSDocThis(changes, sourceFile, containingFunction, typeNode);
|
||||
}
|
||||
else {
|
||||
changes.tryInsertThisTypeAnnotation(sourceFile, containingFunction, typeNode);
|
||||
}
|
||||
}
|
||||
|
||||
function annotateJSDocThis(changes: textChanges.ChangeTracker, sourceFile: SourceFile, containingFunction: FunctionLike, typeNode: TypeNode) {
|
||||
addJSDocTags(changes, sourceFile, containingFunction, [
|
||||
createJSDocThisTag(createJSDocTypeExpression(typeNode)),
|
||||
]);
|
||||
}
|
||||
|
||||
function annotateSetAccessor(changes: textChanges.ChangeTracker, sourceFile: SourceFile, setAccessorDeclaration: SetAccessorDeclaration, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken): void {
|
||||
const param = firstOrUndefined(setAccessorDeclaration.parameters);
|
||||
if (param && isIdentifier(setAccessorDeclaration.name) && isIdentifier(param.name)) {
|
||||
@@ -317,7 +362,7 @@ namespace ts.codefix {
|
||||
return InferFromReference.unifyFromContext(types, checker);
|
||||
}
|
||||
|
||||
function inferTypeForParametersFromUsage(containingFunction: FunctionLike, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined {
|
||||
function inferFunctionReferencesFromUsage(containingFunction: FunctionLike, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): ReadonlyArray<Identifier> | undefined {
|
||||
let searchToken;
|
||||
switch (containingFunction.kind) {
|
||||
case SyntaxKind.Constructor:
|
||||
@@ -335,9 +380,12 @@ namespace ts.codefix {
|
||||
searchToken = containingFunction.name;
|
||||
break;
|
||||
}
|
||||
if (searchToken) {
|
||||
return InferFromReference.inferTypeForParametersFromReferences(getReferences(searchToken, program, cancellationToken), containingFunction, program, cancellationToken);
|
||||
|
||||
if (!searchToken) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return getReferences(searchToken, program, cancellationToken);
|
||||
}
|
||||
|
||||
interface ParameterInference {
|
||||
@@ -364,6 +412,7 @@ namespace ts.codefix {
|
||||
constructContexts?: CallContext[];
|
||||
numberIndexContext?: UsageContext;
|
||||
stringIndexContext?: UsageContext;
|
||||
candidateThisTypes?: Type[];
|
||||
}
|
||||
|
||||
export function inferTypesFromReferences(references: ReadonlyArray<Identifier>, checker: TypeChecker, cancellationToken: CancellationToken): Type[] {
|
||||
@@ -375,15 +424,12 @@ namespace ts.codefix {
|
||||
return inferFromContext(usageContext, checker);
|
||||
}
|
||||
|
||||
export function inferTypeForParametersFromReferences(references: ReadonlyArray<Identifier>, declaration: FunctionLike, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined {
|
||||
const checker = program.getTypeChecker();
|
||||
if (references.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
if (!declaration.parameters) {
|
||||
export function inferTypeForParametersFromReferences(references: ReadonlyArray<Identifier> | undefined, declaration: FunctionLike, program: Program, cancellationToken: CancellationToken): ParameterInference[] | undefined {
|
||||
if (references === undefined || references.length === 0 || !declaration.parameters) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const checker = program.getTypeChecker();
|
||||
const usageContext: UsageContext = {};
|
||||
for (const reference of references) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
@@ -421,6 +467,22 @@ namespace ts.codefix {
|
||||
});
|
||||
}
|
||||
|
||||
export function inferTypeForThisFromReferences(references: ReadonlyArray<Identifier>, program: Program, cancellationToken: CancellationToken) {
|
||||
if (references.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const checker = program.getTypeChecker();
|
||||
const usageContext: UsageContext = {};
|
||||
|
||||
for (const reference of references) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
inferTypeFromContext(reference, checker, usageContext);
|
||||
}
|
||||
|
||||
return unifyFromContext(usageContext.candidateThisTypes || emptyArray, checker);
|
||||
}
|
||||
|
||||
function inferTypeFromContext(node: Expression, checker: TypeChecker, usageContext: UsageContext): void {
|
||||
while (isRightSideOfQualifiedNameOrPropertyAccess(node)) {
|
||||
node = <Expression>node.parent;
|
||||
@@ -455,6 +517,13 @@ namespace ts.codefix {
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
inferTypeFromPropertyElementExpressionContext(<ElementAccessExpression>node.parent, node, checker, usageContext);
|
||||
break;
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
inferTypeFromPropertyAssignment(<PropertyAssignment | ShorthandPropertyAssignment>node.parent, checker, usageContext);
|
||||
break;
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
inferTypeFromPropertyDeclaration(<PropertyDeclaration>node.parent, checker, usageContext);
|
||||
break;
|
||||
case SyntaxKind.VariableDeclaration: {
|
||||
const { name, initializer } = node.parent as VariableDeclaration;
|
||||
if (node === name) {
|
||||
@@ -647,6 +716,21 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function inferTypeFromPropertyAssignment(assignment: PropertyAssignment | ShorthandPropertyAssignment, checker: TypeChecker, usageContext: UsageContext) {
|
||||
const objectLiteral = isShorthandPropertyAssignment(assignment) ?
|
||||
assignment.parent :
|
||||
assignment.parent.parent;
|
||||
const nodeWithRealType = isVariableDeclaration(objectLiteral.parent) ?
|
||||
objectLiteral.parent :
|
||||
objectLiteral;
|
||||
|
||||
addCandidateThisType(usageContext, checker.getTypeAtLocation(nodeWithRealType));
|
||||
}
|
||||
|
||||
function inferTypeFromPropertyDeclaration(declaration: PropertyDeclaration, checker: TypeChecker, usageContext: UsageContext) {
|
||||
addCandidateThisType(usageContext, checker.getTypeAtLocation(declaration.parent));
|
||||
}
|
||||
|
||||
interface Priority {
|
||||
high: (t: Type) => boolean;
|
||||
low: (t: Type) => boolean;
|
||||
@@ -841,6 +925,12 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function addCandidateThisType(context: UsageContext, type: Type | undefined) {
|
||||
if (type && !(type.flags & TypeFlags.Any) && !(type.flags & TypeFlags.Never)) {
|
||||
(context.candidateThisTypes || (context.candidateThisTypes = [])).push(type);
|
||||
}
|
||||
}
|
||||
|
||||
function hasCallContext(usageContext: UsageContext | undefined): boolean {
|
||||
return !!usageContext && !!usageContext.callContexts;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,15 @@ namespace ts.FindAllReferences {
|
||||
export const enum EntryKind { Span, Node, StringLiteral, SearchedLocalFoundProperty, SearchedPropertyFoundLocal }
|
||||
export type NodeEntryKind = EntryKind.Node | EntryKind.StringLiteral | EntryKind.SearchedLocalFoundProperty | EntryKind.SearchedPropertyFoundLocal;
|
||||
export type Entry = NodeEntry | SpanEntry;
|
||||
export interface ContextWithStartAndEndNode {
|
||||
start: Node;
|
||||
end: Node;
|
||||
}
|
||||
export type ContextNode = Node | ContextWithStartAndEndNode;
|
||||
export interface NodeEntry {
|
||||
readonly kind: NodeEntryKind;
|
||||
readonly node: Node;
|
||||
readonly context?: ContextNode;
|
||||
}
|
||||
export interface SpanEntry {
|
||||
readonly kind: EntryKind.Span;
|
||||
@@ -26,7 +32,143 @@ namespace ts.FindAllReferences {
|
||||
readonly textSpan: TextSpan;
|
||||
}
|
||||
export function nodeEntry(node: Node, kind: NodeEntryKind = EntryKind.Node): NodeEntry {
|
||||
return { kind, node: (node as NamedDeclaration).name || node };
|
||||
return {
|
||||
kind,
|
||||
node: (node as NamedDeclaration).name || node,
|
||||
context: getContextNodeForNodeEntry(node)
|
||||
};
|
||||
}
|
||||
|
||||
export function isContextWithStartAndEndNode(node: ContextNode): node is ContextWithStartAndEndNode {
|
||||
return node && (node as Node).kind === undefined;
|
||||
}
|
||||
|
||||
function getContextNodeForNodeEntry(node: Node): ContextNode | undefined {
|
||||
if (isDeclaration(node)) {
|
||||
return getContextNode(node);
|
||||
}
|
||||
|
||||
if (!node.parent) return undefined;
|
||||
|
||||
if (!isDeclaration(node.parent) && !isExportAssignment(node.parent)) {
|
||||
// Special property assignment in javascript
|
||||
if (isInJSFile(node)) {
|
||||
const binaryExpression = isBinaryExpression(node.parent) ?
|
||||
node.parent :
|
||||
isPropertyAccessExpression(node.parent) &&
|
||||
isBinaryExpression(node.parent.parent) &&
|
||||
node.parent.parent.left === node.parent ?
|
||||
node.parent.parent :
|
||||
undefined;
|
||||
if (binaryExpression && getAssignmentDeclarationKind(binaryExpression) !== AssignmentDeclarationKind.None) {
|
||||
return getContextNode(binaryExpression);
|
||||
}
|
||||
}
|
||||
|
||||
// Jsx Tags
|
||||
if (isJsxOpeningElement(node.parent) || isJsxClosingElement(node.parent)) {
|
||||
return node.parent.parent;
|
||||
}
|
||||
else if (isJsxSelfClosingElement(node.parent) ||
|
||||
isLabeledStatement(node.parent) ||
|
||||
isBreakOrContinueStatement(node.parent)) {
|
||||
return node.parent;
|
||||
}
|
||||
else if (isStringLiteralLike(node)) {
|
||||
const validImport = tryGetImportFromModuleSpecifier(node);
|
||||
if (validImport) {
|
||||
const declOrStatement = findAncestor(validImport, node =>
|
||||
isDeclaration(node) ||
|
||||
isStatement(node) ||
|
||||
isJSDocTag(node)
|
||||
)! as NamedDeclaration | Statement | JSDocTag;
|
||||
return isDeclaration(declOrStatement) ?
|
||||
getContextNode(declOrStatement) :
|
||||
declOrStatement;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle computed property name
|
||||
const propertyName = findAncestor(node, isComputedPropertyName);
|
||||
return propertyName ?
|
||||
getContextNode(propertyName.parent) :
|
||||
undefined;
|
||||
}
|
||||
|
||||
if (node.parent.name === node || // node is name of declaration, use parent
|
||||
isConstructorDeclaration(node.parent) ||
|
||||
isExportAssignment(node.parent) ||
|
||||
// Property name of the import export specifier or binding pattern, use parent
|
||||
((isImportOrExportSpecifier(node.parent) || isBindingElement(node.parent))
|
||||
&& node.parent.propertyName === node) ||
|
||||
// Is default export
|
||||
(node.kind === SyntaxKind.DefaultKeyword && hasModifier(node.parent, ModifierFlags.ExportDefault))) {
|
||||
return getContextNode(node.parent);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function getContextNode(node: NamedDeclaration | BinaryExpression | ForInOrOfStatement | undefined): ContextNode | undefined {
|
||||
if (!node) return undefined;
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return !isVariableDeclarationList(node.parent) || node.parent.declarations.length !== 1 ?
|
||||
node :
|
||||
isVariableStatement(node.parent.parent) ?
|
||||
node.parent.parent :
|
||||
isForInOrOfStatement(node.parent.parent) ?
|
||||
getContextNode(node.parent.parent) :
|
||||
node.parent;
|
||||
|
||||
case SyntaxKind.BindingElement:
|
||||
return getContextNode(node.parent.parent as NamedDeclaration);
|
||||
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
return node.parent.parent.parent;
|
||||
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
case SyntaxKind.NamespaceImport:
|
||||
return node.parent.parent;
|
||||
|
||||
case SyntaxKind.ImportClause:
|
||||
return node.parent;
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return isExpressionStatement(node.parent) ?
|
||||
node.parent :
|
||||
node;
|
||||
|
||||
case SyntaxKind.ForOfStatement:
|
||||
case SyntaxKind.ForInStatement:
|
||||
return {
|
||||
start: (node as ForInOrOfStatement).initializer,
|
||||
end: (node as ForInOrOfStatement).expression
|
||||
};
|
||||
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
return isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent) ?
|
||||
getContextNode(
|
||||
findAncestor(node.parent, node =>
|
||||
isBinaryExpression(node) || isForInOrOfStatement(node)
|
||||
) as BinaryExpression | ForInOrOfStatement
|
||||
) :
|
||||
node;
|
||||
|
||||
default:
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
export function toContextSpan(textSpan: TextSpan, sourceFile: SourceFile, context?: ContextNode): { contextSpan: TextSpan } | undefined {
|
||||
if (!context) return undefined;
|
||||
const contextSpan = isContextWithStartAndEndNode(context) ?
|
||||
getTextSpan(context.start, sourceFile, context.end) :
|
||||
getTextSpan(context, sourceFile);
|
||||
return contextSpan.start !== textSpan.start || contextSpan.length !== textSpan.length ?
|
||||
{ contextSpan } :
|
||||
undefined;
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
@@ -123,7 +265,16 @@ namespace ts.FindAllReferences {
|
||||
const { symbol } = def;
|
||||
const { displayParts, kind } = getDefinitionKindAndDisplayParts(symbol, checker, originalNode);
|
||||
const name = displayParts.map(p => p.text).join("");
|
||||
return { node: symbol.declarations ? getNameOfDeclaration(first(symbol.declarations)) || first(symbol.declarations) : originalNode, name, kind, displayParts };
|
||||
const declaration = symbol.declarations ? first(symbol.declarations) : undefined;
|
||||
return {
|
||||
node: declaration ?
|
||||
getNameOfDeclaration(declaration) || declaration :
|
||||
originalNode,
|
||||
name,
|
||||
kind,
|
||||
displayParts,
|
||||
context: getContextNode(declaration)
|
||||
};
|
||||
}
|
||||
case DefinitionKind.Label: {
|
||||
const { node } = def;
|
||||
@@ -150,9 +301,19 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
})();
|
||||
|
||||
const { node, name, kind, displayParts } = info;
|
||||
const { node, name, kind, displayParts, context } = info;
|
||||
const sourceFile = node.getSourceFile();
|
||||
return { containerKind: ScriptElementKind.unknown, containerName: "", fileName: sourceFile.fileName, kind, name, textSpan: getTextSpan(isComputedPropertyName(node) ? node.expression : node, sourceFile), displayParts };
|
||||
const textSpan = getTextSpan(isComputedPropertyName(node) ? node.expression : node, sourceFile);
|
||||
return {
|
||||
containerKind: ScriptElementKind.unknown,
|
||||
containerName: "",
|
||||
fileName: sourceFile.fileName,
|
||||
kind,
|
||||
name,
|
||||
textSpan,
|
||||
displayParts,
|
||||
...toContextSpan(textSpan, sourceFile, context)
|
||||
};
|
||||
}
|
||||
|
||||
function getDefinitionKindAndDisplayParts(symbol: Symbol, checker: TypeChecker, node: Node): { displayParts: SymbolDisplayPart[], kind: ScriptElementKind } {
|
||||
@@ -168,14 +329,13 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
export function toReferenceEntry(entry: Entry): ReferenceEntry {
|
||||
const { textSpan, fileName } = entryToDocumentSpan(entry);
|
||||
const documentSpan = entryToDocumentSpan(entry);
|
||||
if (entry.kind === EntryKind.Span) {
|
||||
return { textSpan, fileName, isWriteAccess: false, isDefinition: false };
|
||||
return { ...documentSpan, isWriteAccess: false, isDefinition: false };
|
||||
}
|
||||
const { kind, node } = entry;
|
||||
return {
|
||||
textSpan,
|
||||
fileName,
|
||||
...documentSpan,
|
||||
isWriteAccess: isWriteAccessForReference(node),
|
||||
isDefinition: node.kind === SyntaxKind.DefaultKeyword
|
||||
|| !!getDeclarationFromName(node)
|
||||
@@ -190,7 +350,12 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
else {
|
||||
const sourceFile = entry.node.getSourceFile();
|
||||
return { textSpan: getTextSpan(entry.node, sourceFile), fileName: sourceFile.fileName };
|
||||
const textSpan = getTextSpan(entry.node, sourceFile);
|
||||
return {
|
||||
textSpan,
|
||||
fileName: sourceFile.fileName,
|
||||
...toContextSpan(textSpan, sourceFile, entry.context)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,14 +388,16 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
function toImplementationLocation(entry: Entry, checker: TypeChecker): ImplementationLocation {
|
||||
const documentSpan = entryToDocumentSpan(entry);
|
||||
if (entry.kind !== EntryKind.Span) {
|
||||
const { node } = entry;
|
||||
const sourceFile = node.getSourceFile();
|
||||
return { textSpan: getTextSpan(node, sourceFile), fileName: sourceFile.fileName, ...implementationKindDisplayParts(node, checker) };
|
||||
return {
|
||||
...documentSpan,
|
||||
...implementationKindDisplayParts(node, checker)
|
||||
};
|
||||
}
|
||||
else {
|
||||
const { textSpan, fileName } = entry;
|
||||
return { textSpan, fileName, kind: ScriptElementKind.unknown, displayParts: [] };
|
||||
return { ...documentSpan, kind: ScriptElementKind.unknown, displayParts: [] };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,26 +424,32 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
export function toHighlightSpan(entry: Entry): { fileName: string, span: HighlightSpan } {
|
||||
const documentSpan = entryToDocumentSpan(entry);
|
||||
if (entry.kind === EntryKind.Span) {
|
||||
const { fileName, textSpan } = entry;
|
||||
return { fileName, span: { textSpan, kind: HighlightSpanKind.reference } };
|
||||
return {
|
||||
fileName: documentSpan.fileName,
|
||||
span: {
|
||||
textSpan: documentSpan.textSpan,
|
||||
kind: HighlightSpanKind.reference
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const { node, kind } = entry;
|
||||
const sourceFile = node.getSourceFile();
|
||||
const writeAccess = isWriteAccessForReference(node);
|
||||
const writeAccess = isWriteAccessForReference(entry.node);
|
||||
const span: HighlightSpan = {
|
||||
textSpan: getTextSpan(node, sourceFile),
|
||||
textSpan: documentSpan.textSpan,
|
||||
kind: writeAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference,
|
||||
isInString: kind === EntryKind.StringLiteral ? true : undefined,
|
||||
isInString: entry.kind === EntryKind.StringLiteral ? true : undefined,
|
||||
...documentSpan.contextSpan && { contextSpan: documentSpan.contextSpan }
|
||||
};
|
||||
return { fileName: sourceFile.fileName, span };
|
||||
return { fileName: documentSpan.fileName, span };
|
||||
}
|
||||
|
||||
function getTextSpan(node: Node, sourceFile: SourceFile): TextSpan {
|
||||
function getTextSpan(node: Node, sourceFile: SourceFile, endNode?: Node): TextSpan {
|
||||
let start = node.getStart(sourceFile);
|
||||
let end = node.getEnd();
|
||||
let end = (endNode || node).getEnd();
|
||||
if (node.kind === SyntaxKind.StringLiteral) {
|
||||
Debug.assert(endNode === undefined);
|
||||
start += 1;
|
||||
end -= 1;
|
||||
}
|
||||
|
||||
@@ -273,13 +273,19 @@ namespace ts.GoToDefinition {
|
||||
function createDefinitionInfoFromName(declaration: Declaration, symbolKind: ScriptElementKind, symbolName: string, containerName: string): DefinitionInfo {
|
||||
const name = getNameOfDeclaration(declaration) || declaration;
|
||||
const sourceFile = name.getSourceFile();
|
||||
const textSpan = createTextSpanFromNode(name, sourceFile);
|
||||
return {
|
||||
fileName: sourceFile.fileName,
|
||||
textSpan: createTextSpanFromNode(name, sourceFile),
|
||||
textSpan,
|
||||
kind: symbolKind,
|
||||
name: symbolName,
|
||||
containerKind: undefined!, // TODO: GH#18217
|
||||
containerName
|
||||
containerName,
|
||||
...FindAllReferences.toContextSpan(
|
||||
textSpan,
|
||||
sourceFile,
|
||||
FindAllReferences.getContextNode(declaration)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1544,13 +1544,17 @@ namespace ts {
|
||||
|
||||
/// References and Occurrences
|
||||
function getOccurrencesAtPosition(fileName: string, position: number): ReadonlyArray<ReferenceEntry> | undefined {
|
||||
return flatMap(getDocumentHighlights(fileName, position, [fileName]), entry => entry.highlightSpans.map<ReferenceEntry>(highlightSpan => ({
|
||||
fileName: entry.fileName,
|
||||
textSpan: highlightSpan.textSpan,
|
||||
isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference,
|
||||
isDefinition: false,
|
||||
isInString: highlightSpan.isInString,
|
||||
})));
|
||||
return flatMap(
|
||||
getDocumentHighlights(fileName, position, [fileName]),
|
||||
entry => entry.highlightSpans.map<ReferenceEntry>(highlightSpan => ({
|
||||
fileName: entry.fileName,
|
||||
textSpan: highlightSpan.textSpan,
|
||||
isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference,
|
||||
isDefinition: false,
|
||||
...highlightSpan.isInString && { isInString: true },
|
||||
...highlightSpan.contextSpan && { contextSpan: highlightSpan.contextSpan }
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
function getDocumentHighlights(fileName: string, position: number, filesToSearch: ReadonlyArray<string>): DocumentHighlights[] | undefined {
|
||||
@@ -1568,8 +1572,14 @@ namespace ts {
|
||||
const node = getTouchingPropertyName(sourceFile, position);
|
||||
if (isIdentifier(node) && (isJsxOpeningElement(node.parent) || isJsxClosingElement(node.parent)) && isIntrinsicJsxName(node.escapedText)) {
|
||||
const { openingElement, closingElement } = node.parent.parent;
|
||||
return [openingElement, closingElement].map((node): RenameLocation =>
|
||||
({ fileName: sourceFile.fileName, textSpan: createTextSpanFromNode(node.tagName, sourceFile) }));
|
||||
return [openingElement, closingElement].map((node): RenameLocation => {
|
||||
const textSpan = createTextSpanFromNode(node.tagName, sourceFile);
|
||||
return {
|
||||
fileName: sourceFile.fileName,
|
||||
textSpan,
|
||||
...FindAllReferences.toContextSpan(textSpan, sourceFile, node.parent)
|
||||
};
|
||||
});
|
||||
}
|
||||
else {
|
||||
return getReferencesWorker(node, position, { findInStrings, findInComments, providePrefixAndSuffixTextForRename, isForRename: true },
|
||||
|
||||
@@ -222,6 +222,12 @@ namespace ts.textChanges {
|
||||
|
||||
export type TypeAnnotatable = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertyDeclaration | PropertySignature;
|
||||
|
||||
export type ThisTypeAnnotatable = FunctionDeclaration | FunctionExpression;
|
||||
|
||||
export function isThisTypeAnnotatable(containingFunction: FunctionLike): containingFunction is ThisTypeAnnotatable {
|
||||
return isFunctionExpression(containingFunction) || isFunctionDeclaration(containingFunction);
|
||||
}
|
||||
|
||||
export class ChangeTracker {
|
||||
private readonly changes: Change[] = [];
|
||||
private readonly newFiles: { readonly oldFile: SourceFile | undefined, readonly fileName: string, readonly statements: ReadonlyArray<Statement> }[] = [];
|
||||
@@ -393,6 +399,13 @@ namespace ts.textChanges {
|
||||
this.insertNodeAt(sourceFile, endNode.end, type, { prefix: ": " });
|
||||
}
|
||||
|
||||
public tryInsertThisTypeAnnotation(sourceFile: SourceFile, node: ThisTypeAnnotatable, type: TypeNode): void {
|
||||
const start = findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile)!.getStart(sourceFile) + 1;
|
||||
const suffix = node.parameters.length ? ", " : "";
|
||||
|
||||
this.insertNodeAt(sourceFile, start, type, { prefix: "this: ", suffix });
|
||||
}
|
||||
|
||||
public insertTypeParameters(sourceFile: SourceFile, node: SignatureDeclaration, typeParameters: ReadonlyArray<TypeParameterDeclaration>): void {
|
||||
// If no `(`, is an arrow function `x => x`, so use the pos of the first parameter
|
||||
const start = (findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile) || first(node.parameters)).getStart(sourceFile);
|
||||
|
||||
@@ -613,6 +613,13 @@ namespace ts {
|
||||
*/
|
||||
originalTextSpan?: TextSpan;
|
||||
originalFileName?: string;
|
||||
|
||||
/**
|
||||
* If DocumentSpan.textSpan is the span for name of the declaration,
|
||||
* then this is the span for relevant declaration
|
||||
*/
|
||||
contextSpan?: TextSpan;
|
||||
originalContextSpan?: TextSpan;
|
||||
}
|
||||
|
||||
export interface RenameLocation extends DocumentSpan {
|
||||
@@ -647,6 +654,7 @@ namespace ts {
|
||||
fileName?: string;
|
||||
isInString?: true;
|
||||
textSpan: TextSpan;
|
||||
contextSpan?: TextSpan;
|
||||
kind: HighlightSpanKind;
|
||||
}
|
||||
|
||||
|
||||
@@ -1190,8 +1190,8 @@ namespace ts {
|
||||
return !!range && shouldBeReference === tripleSlashDirectivePrefixRegex.test(sourceFile.text.substring(range.pos, range.end));
|
||||
}
|
||||
|
||||
export function createTextSpanFromNode(node: Node, sourceFile?: SourceFile): TextSpan {
|
||||
return createTextSpanFromBounds(node.getStart(sourceFile), node.getEnd());
|
||||
export function createTextSpanFromNode(node: Node, sourceFile?: SourceFile, endNode?: Node): TextSpan {
|
||||
return createTextSpanFromBounds(node.getStart(sourceFile), (endNode || node).getEnd());
|
||||
}
|
||||
|
||||
export function createTextRangeFromNode(node: Node, sourceFile: SourceFile): TextRange {
|
||||
|
||||
@@ -1,28 +1,43 @@
|
||||
namespace ts.projectSystem {
|
||||
function protocolFileSpanFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions): protocol.FileSpan {
|
||||
return { file: file.path, ...protocolTextSpanFromSubstring(file.content, substring, options) };
|
||||
interface DocumentSpanFromSubstring {
|
||||
file: File;
|
||||
text: string;
|
||||
options?: SpanFromSubstringOptions;
|
||||
contextText?: string;
|
||||
contextOptions?: SpanFromSubstringOptions;
|
||||
}
|
||||
|
||||
function documentSpanFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions): DocumentSpan {
|
||||
return { fileName: file.path, textSpan: textSpanFromSubstring(file.content, substring, options) };
|
||||
}
|
||||
|
||||
function renameLocation(file: File, substring: string, options?: SpanFromSubstringOptions): RenameLocation {
|
||||
return documentSpanFromSubstring(file, substring, options);
|
||||
}
|
||||
|
||||
function makeReferenceItem(file: File, isDefinition: boolean, text: string, lineText: string, options?: SpanFromSubstringOptions): protocol.ReferencesResponseItem {
|
||||
function documentSpanFromSubstring({ file, text, contextText, options, contextOptions }: DocumentSpanFromSubstring): DocumentSpan {
|
||||
const contextSpan = contextText !== undefined ? documentSpanFromSubstring({ file, text: contextText, options: contextOptions }) : undefined;
|
||||
return {
|
||||
...protocolFileSpanFromSubstring(file, text, options),
|
||||
fileName: file.path,
|
||||
textSpan: textSpanFromSubstring(file.content, text, options),
|
||||
...contextSpan && { contextSpan: contextSpan.textSpan }
|
||||
};
|
||||
}
|
||||
|
||||
function renameLocation(input: DocumentSpanFromSubstring): RenameLocation {
|
||||
return documentSpanFromSubstring(input);
|
||||
}
|
||||
|
||||
interface MakeReferenceItem extends DocumentSpanFromSubstring {
|
||||
isDefinition: boolean;
|
||||
lineText: string;
|
||||
}
|
||||
function makeReferenceItem({ isDefinition, lineText, ...rest }: MakeReferenceItem): protocol.ReferencesResponseItem {
|
||||
return {
|
||||
...protocolFileSpanWithContextFromSubstring(rest),
|
||||
isDefinition,
|
||||
isWriteAccess: isDefinition,
|
||||
lineText,
|
||||
};
|
||||
}
|
||||
|
||||
function makeReferenceEntry(file: File, isDefinition: boolean, text: string, options?: SpanFromSubstringOptions): ReferenceEntry {
|
||||
interface MakeReferenceEntry extends DocumentSpanFromSubstring {
|
||||
isDefinition: boolean;
|
||||
}
|
||||
function makeReferenceEntry({ isDefinition, ...rest }: MakeReferenceEntry): ReferenceEntry {
|
||||
return {
|
||||
...documentSpanFromSubstring(file, text, options),
|
||||
...documentSpanFromSubstring(rest),
|
||||
isDefinition,
|
||||
isWriteAccess: isDefinition,
|
||||
isInString: undefined,
|
||||
@@ -190,7 +205,13 @@ namespace ts.projectSystem {
|
||||
it("goToDefinition", () => {
|
||||
const session = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.DefinitionRequest, protocol.DefinitionResponse>(session, protocol.CommandTypes.Definition, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual(response, [protocolFileSpanFromSubstring(aTs, "fnA")]);
|
||||
assert.deepEqual(response, [
|
||||
protocolFileSpanWithContextFromSubstring({
|
||||
file: aTs,
|
||||
text: "fnA",
|
||||
contextText: "export function fnA() {}"
|
||||
})
|
||||
]);
|
||||
verifySingleInferredProject(session);
|
||||
});
|
||||
|
||||
@@ -199,7 +220,13 @@ namespace ts.projectSystem {
|
||||
const response = executeSessionRequest<protocol.DefinitionAndBoundSpanRequest, protocol.DefinitionAndBoundSpanResponse>(session, protocol.CommandTypes.DefinitionAndBoundSpan, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual(response, {
|
||||
textSpan: protocolTextSpanFromSubstring(userTs.content, "fnA"),
|
||||
definitions: [protocolFileSpanFromSubstring(aTs, "fnA")],
|
||||
definitions: [
|
||||
protocolFileSpanWithContextFromSubstring({
|
||||
file: aTs,
|
||||
text: "fnA",
|
||||
contextText: "export function fnA() {}"
|
||||
})
|
||||
],
|
||||
});
|
||||
verifySingleInferredProject(session);
|
||||
});
|
||||
@@ -209,7 +236,13 @@ namespace ts.projectSystem {
|
||||
const response = executeSessionRequest<protocol.DefinitionAndBoundSpanRequest, protocol.DefinitionAndBoundSpanResponse>(session, protocol.CommandTypes.DefinitionAndBoundSpan, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual(response, {
|
||||
textSpan: protocolTextSpanFromSubstring(userTs.content, "fnA"),
|
||||
definitions: [protocolFileSpanFromSubstring(aTs, "fnA")],
|
||||
definitions: [
|
||||
protocolFileSpanWithContextFromSubstring({
|
||||
file: aTs,
|
||||
text: "fnA",
|
||||
contextText: "export function fnA() {}"
|
||||
})
|
||||
],
|
||||
});
|
||||
checkNumberOfProjects(session.getProjectService(), { configuredProjects: 1 });
|
||||
verifyUserTsConfigProject(session);
|
||||
@@ -230,14 +263,25 @@ namespace ts.projectSystem {
|
||||
it("goToType", () => {
|
||||
const session = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.TypeDefinitionRequest, protocol.TypeDefinitionResponse>(session, protocol.CommandTypes.TypeDefinition, protocolFileLocationFromSubstring(userTs, "instanceA"));
|
||||
assert.deepEqual(response, [protocolFileSpanFromSubstring(aTs, "IfaceA")]);
|
||||
assert.deepEqual(response, [
|
||||
protocolFileSpanWithContextFromSubstring({
|
||||
file: aTs,
|
||||
text: "IfaceA",
|
||||
contextText: "export interface IfaceA {}"
|
||||
})
|
||||
]);
|
||||
verifySingleInferredProject(session);
|
||||
});
|
||||
|
||||
it("goToImplementation", () => {
|
||||
const session = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.ImplementationRequest, protocol.ImplementationResponse>(session, protocol.CommandTypes.Implementation, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual(response, [protocolFileSpanFromSubstring(aTs, "fnA")]);
|
||||
assert.deepEqual(response, [
|
||||
protocolFileSpanWithContextFromSubstring({
|
||||
file: aTs,
|
||||
text: "fnA",
|
||||
contextText: "export function fnA() {}"
|
||||
})]);
|
||||
verifySingleInferredProject(session);
|
||||
});
|
||||
|
||||
@@ -245,7 +289,13 @@ namespace ts.projectSystem {
|
||||
const session = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.DefinitionRequest, protocol.DefinitionResponse>(session, CommandNames.Definition, protocolFileLocationFromSubstring(userTs, "fnB()"));
|
||||
// bTs does not exist, so stick with bDts
|
||||
assert.deepEqual(response, [protocolFileSpanFromSubstring(bDts, "fnB")]);
|
||||
assert.deepEqual(response, [
|
||||
protocolFileSpanWithContextFromSubstring({
|
||||
file: bDts,
|
||||
text: "fnB",
|
||||
contextText: "export declare function fnB(): void;"
|
||||
})
|
||||
]);
|
||||
verifySingleInferredProject(session);
|
||||
});
|
||||
|
||||
@@ -254,7 +304,10 @@ namespace ts.projectSystem {
|
||||
const response = executeSessionRequest<protocol.NavtoRequest, protocol.NavtoResponse>(session, CommandNames.Navto, { file: userTs.path, searchValue: "fn" });
|
||||
assert.deepEqual<ReadonlyArray<protocol.NavtoItem> | undefined>(response, [
|
||||
{
|
||||
...protocolFileSpanFromSubstring(bDts, "export declare function fnB(): void;"),
|
||||
...protocolFileSpanFromSubstring({
|
||||
file: bDts,
|
||||
text: "export declare function fnB(): void;"
|
||||
}),
|
||||
name: "fnB",
|
||||
matchKind: "prefix",
|
||||
isCaseSensitive: true,
|
||||
@@ -262,7 +315,10 @@ namespace ts.projectSystem {
|
||||
kindModifiers: "export,declare",
|
||||
},
|
||||
{
|
||||
...protocolFileSpanFromSubstring(userTs, "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }"),
|
||||
...protocolFileSpanFromSubstring({
|
||||
file: userTs,
|
||||
text: "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }"
|
||||
}),
|
||||
name: "fnUser",
|
||||
matchKind: "prefix",
|
||||
isCaseSensitive: true,
|
||||
@@ -270,7 +326,10 @@ namespace ts.projectSystem {
|
||||
kindModifiers: "export",
|
||||
},
|
||||
{
|
||||
...protocolFileSpanFromSubstring(aTs, "export function fnA() {}"),
|
||||
...protocolFileSpanFromSubstring({
|
||||
file: aTs,
|
||||
text: "export function fnA() {}"
|
||||
}),
|
||||
name: "fnA",
|
||||
matchKind: "prefix",
|
||||
isCaseSensitive: true,
|
||||
@@ -282,9 +341,20 @@ namespace ts.projectSystem {
|
||||
verifyATsConfigOriginalProject(session);
|
||||
});
|
||||
|
||||
const referenceATs = (aTs: File): protocol.ReferencesResponseItem => makeReferenceItem(aTs, /*isDefinition*/ true, "fnA", "export function fnA() {}");
|
||||
const referenceATs = (aTs: File): protocol.ReferencesResponseItem => makeReferenceItem({
|
||||
file: aTs,
|
||||
isDefinition: true,
|
||||
text: "fnA",
|
||||
contextText: "export function fnA() {}",
|
||||
lineText: "export function fnA() {}"
|
||||
});
|
||||
const referencesUserTs = (userTs: File): ReadonlyArray<protocol.ReferencesResponseItem> => [
|
||||
makeReferenceItem(userTs, /*isDefinition*/ false, "fnA", "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }"),
|
||||
makeReferenceItem({
|
||||
file: userTs,
|
||||
isDefinition: false,
|
||||
text: "fnA",
|
||||
lineText: "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }"
|
||||
}),
|
||||
];
|
||||
|
||||
it("findAllReferences", () => {
|
||||
@@ -325,7 +395,11 @@ namespace ts.projectSystem {
|
||||
assert.deepEqual<ReadonlyArray<ReferencedSymbol>>(responseFull, [
|
||||
{
|
||||
definition: {
|
||||
...documentSpanFromSubstring(aTs, "fnA"),
|
||||
...documentSpanFromSubstring({
|
||||
file: aTs,
|
||||
text: "fnA",
|
||||
contextText: "export function fnA() {}"
|
||||
}),
|
||||
kind: ScriptElementKind.functionElement,
|
||||
name: "function fnA(): void",
|
||||
containerKind: ScriptElementKind.unknown,
|
||||
@@ -342,8 +416,8 @@ namespace ts.projectSystem {
|
||||
],
|
||||
},
|
||||
references: [
|
||||
makeReferenceEntry(userTs, /*isDefinition*/ false, "fnA"),
|
||||
makeReferenceEntry(aTs, /*isDefinition*/ true, "fnA"),
|
||||
makeReferenceEntry({ file: userTs, /*isDefinition*/ isDefinition: false, text: "fnA" }),
|
||||
makeReferenceEntry({ file: aTs, /*isDefinition*/ isDefinition: true, text: "fnA", contextText: "export function fnA() {}" }),
|
||||
],
|
||||
},
|
||||
]);
|
||||
@@ -374,6 +448,12 @@ namespace ts.projectSystem {
|
||||
assert.deepEqual<ReadonlyArray<ReferencedSymbol>>(responseFull, [
|
||||
{
|
||||
definition: {
|
||||
...documentSpanFromSubstring({
|
||||
file: aTs,
|
||||
text: "f",
|
||||
options: { index: 1 },
|
||||
contextText: "function f() {}"
|
||||
}),
|
||||
containerKind: ScriptElementKind.unknown,
|
||||
containerName: "",
|
||||
displayParts: [
|
||||
@@ -386,10 +466,8 @@ namespace ts.projectSystem {
|
||||
spacePart(),
|
||||
keywordPart(SyntaxKind.VoidKeyword),
|
||||
],
|
||||
fileName: aTs.path,
|
||||
kind: ScriptElementKind.functionElement,
|
||||
name: "function f(): void",
|
||||
textSpan: { start: 9, length: 1 },
|
||||
},
|
||||
references: [
|
||||
{
|
||||
@@ -399,13 +477,13 @@ namespace ts.projectSystem {
|
||||
isWriteAccess: false,
|
||||
textSpan: { start: 0, length: 1 },
|
||||
},
|
||||
{
|
||||
fileName: aTs.path,
|
||||
isDefinition: true,
|
||||
isInString: undefined,
|
||||
isWriteAccess: true,
|
||||
textSpan: { start: 9, length: 1 },
|
||||
},
|
||||
makeReferenceEntry({
|
||||
file: aTs,
|
||||
text: "f",
|
||||
options: { index: 1 },
|
||||
contextText: "function f() {}",
|
||||
isDefinition: true
|
||||
})
|
||||
],
|
||||
}
|
||||
]);
|
||||
@@ -417,8 +495,19 @@ namespace ts.projectSystem {
|
||||
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(session, protocol.CommandTypes.References, protocolFileLocationFromSubstring(userTs, "fnB()"));
|
||||
assert.deepEqual<protocol.ReferencesResponseBody | undefined>(response, {
|
||||
refs: [
|
||||
makeReferenceItem(bDts, /*isDefinition*/ true, "fnB", "export declare function fnB(): void;"),
|
||||
makeReferenceItem(userTs, /*isDefinition*/ false, "fnB", "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }"),
|
||||
makeReferenceItem({
|
||||
file: bDts,
|
||||
isDefinition: true,
|
||||
text: "fnB",
|
||||
contextText: "export declare function fnB(): void;",
|
||||
lineText: "export declare function fnB(): void;"
|
||||
}),
|
||||
makeReferenceItem({
|
||||
file: userTs,
|
||||
isDefinition: false,
|
||||
text: "fnB",
|
||||
lineText: "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }"
|
||||
}),
|
||||
],
|
||||
symbolName: "fnB",
|
||||
symbolStartOffset: protocolLocationFromSubstring(userTs.content, "fnB()").offset,
|
||||
@@ -429,11 +518,22 @@ namespace ts.projectSystem {
|
||||
|
||||
const renameATs = (aTs: File): protocol.SpanGroup => ({
|
||||
file: aTs.path,
|
||||
locs: [protocolRenameSpanFromSubstring(aTs.content, "fnA")],
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aTs.content,
|
||||
text: "fnA",
|
||||
contextText: "export function fnA() {}"
|
||||
})
|
||||
],
|
||||
});
|
||||
const renameUserTs = (userTs: File): protocol.SpanGroup => ({
|
||||
file: userTs.path,
|
||||
locs: [protocolRenameSpanFromSubstring(userTs.content, "fnA")],
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: userTs.content,
|
||||
text: "fnA"
|
||||
})
|
||||
],
|
||||
});
|
||||
|
||||
it("renameLocations", () => {
|
||||
@@ -477,8 +577,8 @@ namespace ts.projectSystem {
|
||||
const session = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.RenameFullRequest, protocol.RenameFullResponse>(session, protocol.CommandTypes.RenameLocationsFull, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual<ReadonlyArray<RenameLocation>>(response, [
|
||||
renameLocation(userTs, "fnA"),
|
||||
renameLocation(aTs, "fnA"),
|
||||
renameLocation({ file: userTs, text: "fnA" }),
|
||||
renameLocation({ file: aTs, text: "fnA", contextText: "export function fnA() {}" }),
|
||||
]);
|
||||
verifyATsConfigOriginalProject(session);
|
||||
});
|
||||
@@ -499,11 +599,22 @@ namespace ts.projectSystem {
|
||||
locs: [
|
||||
{
|
||||
file: bDts.path,
|
||||
locs: [protocolRenameSpanFromSubstring(bDts.content, "fnB")],
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: bDts.content,
|
||||
text: "fnB",
|
||||
contextText: "export declare function fnB(): void;"
|
||||
})
|
||||
],
|
||||
},
|
||||
{
|
||||
file: userTs.path,
|
||||
locs: [protocolRenameSpanFromSubstring(userTs.content, "fnB")],
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: userTs.content,
|
||||
text: "fnB"
|
||||
})
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -512,13 +512,68 @@ namespace ts.projectSystem {
|
||||
return { start: toLocation(span.start), end: toLocation(textSpanEnd(span)) };
|
||||
}
|
||||
|
||||
export function protocolRenameSpanFromSubstring(
|
||||
str: string,
|
||||
substring: string,
|
||||
options?: SpanFromSubstringOptions,
|
||||
prefixSuffixText?: { readonly prefixText?: string, readonly suffixText?: string },
|
||||
): protocol.RenameTextSpan {
|
||||
return { ...protocolTextSpanFromSubstring(str, substring, options), ...prefixSuffixText };
|
||||
export interface DocumentSpanFromSubstring {
|
||||
file: File;
|
||||
text: string;
|
||||
options?: SpanFromSubstringOptions;
|
||||
}
|
||||
export function protocolFileSpanFromSubstring({ file, text, options }: DocumentSpanFromSubstring): protocol.FileSpan {
|
||||
return { file: file.path, ...protocolTextSpanFromSubstring(file.content, text, options) };
|
||||
}
|
||||
|
||||
interface FileSpanWithContextFromSubString {
|
||||
file: File;
|
||||
text: string;
|
||||
options?: SpanFromSubstringOptions;
|
||||
contextText?: string;
|
||||
contextOptions?: SpanFromSubstringOptions;
|
||||
}
|
||||
export function protocolFileSpanWithContextFromSubstring({ contextText, contextOptions, ...rest }: FileSpanWithContextFromSubString): protocol.FileSpanWithContext {
|
||||
const result = protocolFileSpanFromSubstring(rest);
|
||||
const contextSpan = contextText !== undefined ?
|
||||
protocolFileSpanFromSubstring({ file: rest.file, text: contextText, options: contextOptions }) :
|
||||
undefined;
|
||||
return contextSpan ?
|
||||
{
|
||||
...result,
|
||||
contextStart: contextSpan.start,
|
||||
contextEnd: contextSpan.end
|
||||
} :
|
||||
result;
|
||||
}
|
||||
|
||||
export interface ProtocolTextSpanWithContextFromString {
|
||||
fileText: string;
|
||||
text: string;
|
||||
options?: SpanFromSubstringOptions;
|
||||
contextText?: string;
|
||||
contextOptions?: SpanFromSubstringOptions;
|
||||
}
|
||||
export function protocolTextSpanWithContextFromSubstring({ fileText, text, options, contextText, contextOptions }: ProtocolTextSpanWithContextFromString): protocol.TextSpanWithContext {
|
||||
const span = textSpanFromSubstring(fileText, text, options);
|
||||
const toLocation = protocolToLocation(fileText);
|
||||
const contextSpan = contextText !== undefined ? textSpanFromSubstring(fileText, contextText, contextOptions) : undefined;
|
||||
return {
|
||||
start: toLocation(span.start),
|
||||
end: toLocation(textSpanEnd(span)),
|
||||
...contextSpan && {
|
||||
contextStart: toLocation(contextSpan.start),
|
||||
contextEnd: toLocation(textSpanEnd(contextSpan))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export interface ProtocolRenameSpanFromSubstring extends ProtocolTextSpanWithContextFromString {
|
||||
prefixSuffixText?: {
|
||||
readonly prefixText?: string;
|
||||
readonly suffixText?: string;
|
||||
};
|
||||
}
|
||||
export function protocolRenameSpanFromSubstring({ prefixSuffixText, ...rest }: ProtocolRenameSpanFromSubstring): protocol.RenameTextSpan {
|
||||
return {
|
||||
...protocolTextSpanWithContextFromSubstring(rest),
|
||||
...prefixSuffixText
|
||||
};
|
||||
}
|
||||
|
||||
export function textSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): TextSpan {
|
||||
|
||||
@@ -69,21 +69,24 @@ namespace ts.projectSystem {
|
||||
openFilesForSession([containerCompositeExec[1]], session);
|
||||
const service = session.getProjectService();
|
||||
checkNumberOfProjects(service, { configuredProjects: 1 });
|
||||
const locationOfMyConst = protocolLocationFromSubstring(containerCompositeExec[1].content, "myConst");
|
||||
const { file: myConstFile, start: myConstStart, end: myConstEnd } = protocolFileSpanFromSubstring({
|
||||
file: containerCompositeExec[1],
|
||||
text: "myConst",
|
||||
});
|
||||
const response = session.executeCommandSeq<protocol.RenameRequest>({
|
||||
command: protocol.CommandTypes.Rename,
|
||||
arguments: {
|
||||
file: containerCompositeExec[1].path,
|
||||
...locationOfMyConst
|
||||
}
|
||||
arguments: { file: myConstFile, ...myConstStart }
|
||||
}).response as protocol.RenameResponseBody;
|
||||
|
||||
|
||||
const myConstLen = "myConst".length;
|
||||
const locationOfMyConstInLib = protocolLocationFromSubstring(containerLib[1].content, "myConst");
|
||||
const locationOfMyConstInLib = protocolFileSpanWithContextFromSubstring({
|
||||
file: containerLib[1],
|
||||
text: "myConst",
|
||||
contextText: "export const myConst = 30;"
|
||||
});
|
||||
const { file: _, ...renameTextOfMyConstInLib } = locationOfMyConstInLib;
|
||||
assert.deepEqual(response.locs, [
|
||||
{ file: containerCompositeExec[1].path, locs: [{ start: locationOfMyConst, end: { line: locationOfMyConst.line, offset: locationOfMyConst.offset + myConstLen } }] },
|
||||
{ file: containerLib[1].path, locs: [{ start: locationOfMyConstInLib, end: { line: locationOfMyConstInLib.line, offset: locationOfMyConstInLib.offset + myConstLen } }] }
|
||||
{ file: myConstFile, locs: [{ start: myConstStart, end: myConstEnd }] },
|
||||
{ file: locationOfMyConstInLib.file, locs: [renameTextOfMyConstInLib] }
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -169,7 +172,7 @@ fn5();
|
||||
}
|
||||
function gotoDefintinionFromMainTs(fn: number): SessionAction<protocol.DefinitionAndBoundSpanRequest, protocol.DefinitionInfoAndBoundSpan> {
|
||||
const textSpan = usageSpan(fn);
|
||||
const definition: protocol.FileSpan = { file: dependencyTs.path, ...definitionSpan(fn) };
|
||||
const definition: protocol.FileSpan = { file: dependencyTs.path, ...declarationSpan(fn) };
|
||||
const declareSpaceLength = "declare ".length;
|
||||
return {
|
||||
reqName: "goToDef",
|
||||
@@ -184,7 +187,13 @@ fn5();
|
||||
},
|
||||
expectedResponseNoMap: {
|
||||
// To the dts
|
||||
definitions: [{ file: dtsPath, start: { line: fn, offset: definition.start.offset + declareSpaceLength }, end: { line: fn, offset: definition.end.offset + declareSpaceLength } }],
|
||||
definitions: [{
|
||||
file: dtsPath,
|
||||
start: { line: fn, offset: definition.start.offset + declareSpaceLength },
|
||||
end: { line: fn, offset: definition.end.offset + declareSpaceLength },
|
||||
contextStart: { line: fn, offset: 1 },
|
||||
contextEnd: { line: fn, offset: 37 }
|
||||
}],
|
||||
textSpan
|
||||
},
|
||||
expectedResponseNoDts: {
|
||||
@@ -195,18 +204,29 @@ fn5();
|
||||
};
|
||||
}
|
||||
|
||||
function definitionSpan(fn: number): protocol.TextSpan {
|
||||
return { start: { line: fn, offset: 17 }, end: { line: fn, offset: 20 } };
|
||||
function declarationSpan(fn: number): protocol.TextSpanWithContext {
|
||||
return {
|
||||
start: { line: fn, offset: 17 },
|
||||
end: { line: fn, offset: 20 },
|
||||
contextStart: { line: fn, offset: 1 },
|
||||
contextEnd: { line: fn, offset: 26 }
|
||||
};
|
||||
}
|
||||
function importSpan(fn: number): protocol.TextSpan {
|
||||
return { start: { line: fn + 1, offset: 5 }, end: { line: fn + 1, offset: 8 } };
|
||||
function importSpan(fn: number): protocol.TextSpanWithContext {
|
||||
return {
|
||||
start: { line: fn + 1, offset: 5 },
|
||||
end: { line: fn + 1, offset: 8 },
|
||||
contextStart: { line: 1, offset: 1 },
|
||||
contextEnd: { line: 7, offset: 27 }
|
||||
};
|
||||
}
|
||||
function usageSpan(fn: number): protocol.TextSpan {
|
||||
return { start: { line: fn + 8, offset: 1 }, end: { line: fn + 8, offset: 4 } };
|
||||
}
|
||||
|
||||
function renameFromDependencyTs(fn: number): SessionAction<protocol.RenameRequest, protocol.RenameResponseBody> {
|
||||
const triggerSpan = definitionSpan(fn);
|
||||
const defSpan = declarationSpan(fn);
|
||||
const { contextStart: _, contextEnd: _1, ...triggerSpan } = defSpan;
|
||||
return {
|
||||
reqName: "rename",
|
||||
request: {
|
||||
@@ -224,7 +244,7 @@ fn5();
|
||||
triggerSpan
|
||||
},
|
||||
locs: [
|
||||
{ file: dependencyTs.path, locs: [triggerSpan] }
|
||||
{ file: dependencyTs.path, locs: [defSpan] }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,7 +14,16 @@ namespace ts.projectSystem {
|
||||
canRename: false,
|
||||
localizedErrorMessage: "You cannot rename this element."
|
||||
},
|
||||
locs: [{ file: bTs.path, locs: [protocolRenameSpanFromSubstring(bTs.content, "./a")] }],
|
||||
locs: [{
|
||||
file: bTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: bTs.content,
|
||||
text: "./a",
|
||||
contextText: bTs.content
|
||||
})
|
||||
]
|
||||
}],
|
||||
});
|
||||
|
||||
// rename succeeds with allowRenameOfImportPath enabled in host
|
||||
@@ -30,7 +39,16 @@ namespace ts.projectSystem {
|
||||
kindModifiers: "",
|
||||
triggerSpan: protocolTextSpanFromSubstring(bTs.content, "a", { index: 1 }),
|
||||
},
|
||||
locs: [{ file: bTs.path, locs: [protocolRenameSpanFromSubstring(bTs.content, "./a")] }],
|
||||
locs: [{
|
||||
file: bTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: bTs.content,
|
||||
text: "./a",
|
||||
contextText: bTs.content
|
||||
})
|
||||
]
|
||||
}],
|
||||
});
|
||||
|
||||
// rename succeeds with allowRenameOfImportPath enabled in file
|
||||
@@ -47,7 +65,16 @@ namespace ts.projectSystem {
|
||||
kindModifiers: "",
|
||||
triggerSpan: protocolTextSpanFromSubstring(bTs.content, "a", { index: 1 }),
|
||||
},
|
||||
locs: [{ file: bTs.path, locs: [protocolRenameSpanFromSubstring(bTs.content, "./a")] }],
|
||||
locs: [{
|
||||
file: bTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: bTs.content,
|
||||
text: "./a",
|
||||
contextText: bTs.content
|
||||
})
|
||||
]
|
||||
}],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,8 +100,16 @@ namespace ts.projectSystem {
|
||||
{
|
||||
file: aTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x"),
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 1 }),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aTs.content,
|
||||
text: "x",
|
||||
contextText: "const x = 0;"
|
||||
}),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aTs.content,
|
||||
text: "x",
|
||||
options: { index: 1 }
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -97,8 +132,17 @@ namespace ts.projectSystem {
|
||||
{
|
||||
file: aTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x"),
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 1 }, { prefixText: "x: " }),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aTs.content,
|
||||
text: "x",
|
||||
contextText: "const x = 0;"
|
||||
}),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aTs.content,
|
||||
text: "x",
|
||||
options: { index: 1 },
|
||||
prefixSuffixText: { prefixText: "x: " }
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -122,8 +166,17 @@ namespace ts.projectSystem {
|
||||
{
|
||||
file: aTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x"),
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 1 }, { prefixText: "x: " }),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aTs.content,
|
||||
text: "x",
|
||||
contextText: "const x = 0;"
|
||||
}),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aTs.content,
|
||||
text: "x",
|
||||
options: { index: 1 },
|
||||
prefixSuffixText: { prefixText: "x: " }
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -154,8 +207,18 @@ namespace ts.projectSystem {
|
||||
{
|
||||
file: aTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x"),
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 2 }, { suffixText: " as x" }),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aTs.content,
|
||||
text: "x",
|
||||
contextText: "const x = 1;"
|
||||
}),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aTs.content,
|
||||
text: "x",
|
||||
options: { index: 2 },
|
||||
contextText: "export { x };",
|
||||
prefixSuffixText: { suffixText: " as x" }
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -177,15 +240,32 @@ namespace ts.projectSystem {
|
||||
{
|
||||
file: bTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring(bTs.content, "x"),
|
||||
protocolRenameSpanFromSubstring(bTs.content, "x", { index: 1 })
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: bTs.content,
|
||||
text: "x",
|
||||
contextText: `import { x } from "./a";`
|
||||
}),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: bTs.content,
|
||||
text: "x",
|
||||
options: { index: 1 },
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
file: aTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x"),
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 2 }),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aTs.content,
|
||||
text: "x",
|
||||
contextText: "const x = 1;"
|
||||
}),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aTs.content,
|
||||
text: "x",
|
||||
options: { index: 2 },
|
||||
contextText: "export { x };",
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -58,10 +58,22 @@ namespace ts.projectSystem {
|
||||
|
||||
assert.equal(aFile.content, bFile.content);
|
||||
const abLocs: protocol.RenameTextSpan[] = [
|
||||
protocolRenameSpanFromSubstring(aFile.content, "C"),
|
||||
protocolRenameSpanFromSubstring(aFile.content, "C", { index: 1 }),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aFile.content,
|
||||
text: "C",
|
||||
contextText: `import {C} from "./c/fc";`
|
||||
}),
|
||||
protocolRenameSpanFromSubstring({
|
||||
fileText: aFile.content,
|
||||
text: "C",
|
||||
options: { index: 1 }
|
||||
}),
|
||||
];
|
||||
const span = protocolRenameSpanFromSubstring(cFile.content, "C");
|
||||
const span = protocolRenameSpanFromSubstring({
|
||||
fileText: cFile.content,
|
||||
text: "C",
|
||||
contextText: "export const C = 8"
|
||||
});
|
||||
const cLocs: protocol.RenameTextSpan[] = [span];
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response, {
|
||||
info: {
|
||||
|
||||
+22
-9
@@ -5168,6 +5168,12 @@ declare namespace ts {
|
||||
*/
|
||||
originalTextSpan?: TextSpan;
|
||||
originalFileName?: string;
|
||||
/**
|
||||
* If DocumentSpan.textSpan is the span for name of the declaration,
|
||||
* then this is the span for relevant declaration
|
||||
*/
|
||||
contextSpan?: TextSpan;
|
||||
originalContextSpan?: TextSpan;
|
||||
}
|
||||
interface RenameLocation extends DocumentSpan {
|
||||
readonly prefixText?: string;
|
||||
@@ -5196,6 +5202,7 @@ declare namespace ts {
|
||||
fileName?: string;
|
||||
isInString?: true;
|
||||
textSpan: TextSpan;
|
||||
contextSpan?: TextSpan;
|
||||
kind: HighlightSpanKind;
|
||||
}
|
||||
interface NavigateToItem {
|
||||
@@ -6489,15 +6496,21 @@ declare namespace ts.server.protocol {
|
||||
*/
|
||||
file: string;
|
||||
}
|
||||
interface TextSpanWithContext extends TextSpan {
|
||||
contextStart?: Location;
|
||||
contextEnd?: Location;
|
||||
}
|
||||
interface FileSpanWithContext extends FileSpan, TextSpanWithContext {
|
||||
}
|
||||
interface DefinitionInfoAndBoundSpan {
|
||||
definitions: ReadonlyArray<FileSpan>;
|
||||
definitions: ReadonlyArray<FileSpanWithContext>;
|
||||
textSpan: TextSpan;
|
||||
}
|
||||
/**
|
||||
* Definition response message. Gives text range for definition.
|
||||
*/
|
||||
interface DefinitionResponse extends Response {
|
||||
body?: FileSpan[];
|
||||
body?: FileSpanWithContext[];
|
||||
}
|
||||
interface DefinitionInfoAndBoundSpanReponse extends Response {
|
||||
body?: DefinitionInfoAndBoundSpan;
|
||||
@@ -6506,13 +6519,13 @@ declare namespace ts.server.protocol {
|
||||
* Definition response message. Gives text range for definition.
|
||||
*/
|
||||
interface TypeDefinitionResponse extends Response {
|
||||
body?: FileSpan[];
|
||||
body?: FileSpanWithContext[];
|
||||
}
|
||||
/**
|
||||
* Implementation response message. Gives text range for implementations.
|
||||
*/
|
||||
interface ImplementationResponse extends Response {
|
||||
body?: FileSpan[];
|
||||
body?: FileSpanWithContext[];
|
||||
}
|
||||
/**
|
||||
* Request to get brace completion for a location in the file.
|
||||
@@ -6549,7 +6562,7 @@ declare namespace ts.server.protocol {
|
||||
command: CommandTypes.Occurrences;
|
||||
}
|
||||
/** @deprecated */
|
||||
interface OccurrencesResponseItem extends FileSpan {
|
||||
interface OccurrencesResponseItem extends FileSpanWithContext {
|
||||
/**
|
||||
* True if the occurrence is a write location, false otherwise.
|
||||
*/
|
||||
@@ -6575,7 +6588,7 @@ declare namespace ts.server.protocol {
|
||||
/**
|
||||
* Span augmented with extra information that denotes the kind of the highlighting to be used for span.
|
||||
*/
|
||||
interface HighlightSpan extends TextSpan {
|
||||
interface HighlightSpan extends TextSpanWithContext {
|
||||
kind: HighlightSpanKind;
|
||||
}
|
||||
/**
|
||||
@@ -6605,7 +6618,7 @@ declare namespace ts.server.protocol {
|
||||
interface ReferencesRequest extends FileLocationRequest {
|
||||
command: CommandTypes.References;
|
||||
}
|
||||
interface ReferencesResponseItem extends FileSpan {
|
||||
interface ReferencesResponseItem extends FileSpanWithContext {
|
||||
/** Text of line containing the reference. Including this
|
||||
* with the response avoids latency of editor loading files
|
||||
* to show text of reference line (the server already has
|
||||
@@ -6720,7 +6733,7 @@ declare namespace ts.server.protocol {
|
||||
/** The text spans in this group */
|
||||
locs: RenameTextSpan[];
|
||||
}
|
||||
interface RenameTextSpan extends TextSpan {
|
||||
interface RenameTextSpan extends TextSpanWithContext {
|
||||
readonly prefixText?: string;
|
||||
readonly suffixText?: string;
|
||||
}
|
||||
@@ -9077,6 +9090,7 @@ declare namespace ts.server {
|
||||
private mapDefinitionInfo;
|
||||
private static mapToOriginalLocation;
|
||||
private toFileSpan;
|
||||
private toFileSpanWithContext;
|
||||
private getTypeDefinition;
|
||||
private mapImplementationLocations;
|
||||
private getImplementation;
|
||||
@@ -9134,7 +9148,6 @@ declare namespace ts.server {
|
||||
private mapLocationNavigationBarItems;
|
||||
private getNavigationBarItems;
|
||||
private toLocationNavigationTree;
|
||||
private toLocationTextSpan;
|
||||
private getNavigationTree;
|
||||
private getNavigateToItems;
|
||||
private getFullNavigateToItems;
|
||||
|
||||
@@ -5168,6 +5168,12 @@ declare namespace ts {
|
||||
*/
|
||||
originalTextSpan?: TextSpan;
|
||||
originalFileName?: string;
|
||||
/**
|
||||
* If DocumentSpan.textSpan is the span for name of the declaration,
|
||||
* then this is the span for relevant declaration
|
||||
*/
|
||||
contextSpan?: TextSpan;
|
||||
originalContextSpan?: TextSpan;
|
||||
}
|
||||
interface RenameLocation extends DocumentSpan {
|
||||
readonly prefixText?: string;
|
||||
@@ -5196,6 +5202,7 @@ declare namespace ts {
|
||||
fileName?: string;
|
||||
isInString?: true;
|
||||
textSpan: TextSpan;
|
||||
contextSpan?: TextSpan;
|
||||
kind: HighlightSpanKind;
|
||||
}
|
||||
interface NavigateToItem {
|
||||
|
||||
@@ -128,10 +128,10 @@ function foo3() {
|
||||
}
|
||||
function foo4() {
|
||||
var y = /** @class */ (function () {
|
||||
function class_1() {
|
||||
function y() {
|
||||
}
|
||||
class_1.prototype.m = function () { return x; };
|
||||
return class_1;
|
||||
y.prototype.m = function () { return x; };
|
||||
return y;
|
||||
}());
|
||||
var x;
|
||||
}
|
||||
@@ -156,19 +156,19 @@ function foo7() {
|
||||
}
|
||||
function foo8() {
|
||||
var y = /** @class */ (function () {
|
||||
function class_2() {
|
||||
function class_1() {
|
||||
this.a = x;
|
||||
}
|
||||
return class_2;
|
||||
return class_1;
|
||||
}());
|
||||
var x;
|
||||
}
|
||||
function foo9() {
|
||||
var _a;
|
||||
var y = (_a = /** @class */ (function () {
|
||||
function class_3() {
|
||||
function class_2() {
|
||||
}
|
||||
return class_3;
|
||||
return class_2;
|
||||
}()),
|
||||
_a.a = x,
|
||||
_a);
|
||||
@@ -187,9 +187,9 @@ function foo11() {
|
||||
function f() {
|
||||
var _a;
|
||||
var y = (_a = /** @class */ (function () {
|
||||
function class_4() {
|
||||
function class_3() {
|
||||
}
|
||||
return class_4;
|
||||
return class_3;
|
||||
}()),
|
||||
_a.a = x,
|
||||
_a);
|
||||
@@ -199,10 +199,10 @@ function foo11() {
|
||||
function foo12() {
|
||||
function f() {
|
||||
var y = /** @class */ (function () {
|
||||
function class_5() {
|
||||
function class_4() {
|
||||
this.a = x;
|
||||
}
|
||||
return class_5;
|
||||
return class_4;
|
||||
}());
|
||||
}
|
||||
var x;
|
||||
|
||||
@@ -9,11 +9,11 @@ let x = (new C).foo();
|
||||
|
||||
//// [classExpression4.js]
|
||||
var C = /** @class */ (function () {
|
||||
function class_1() {
|
||||
function C() {
|
||||
}
|
||||
class_1.prototype.foo = function () {
|
||||
C.prototype.foo = function () {
|
||||
return new C();
|
||||
};
|
||||
return class_1;
|
||||
return C;
|
||||
}());
|
||||
var x = (new C).foo();
|
||||
|
||||
@@ -28,9 +28,9 @@ var A = /** @class */ (function () {
|
||||
return A;
|
||||
}());
|
||||
var C = /** @class */ (function (_super) {
|
||||
__extends(class_1, _super);
|
||||
function class_1() {
|
||||
__extends(C, _super);
|
||||
function C() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
return class_1;
|
||||
return C;
|
||||
}(A));
|
||||
|
||||
@@ -47,11 +47,11 @@ var __extends = (this && this.__extends) || (function () {
|
||||
})();
|
||||
exports.__esModule = true;
|
||||
exports.simpleExample = /** @class */ (function () {
|
||||
function class_1() {
|
||||
function simpleExample() {
|
||||
}
|
||||
class_1.getTags = function () { };
|
||||
class_1.prototype.tags = function () { };
|
||||
return class_1;
|
||||
simpleExample.getTags = function () { };
|
||||
simpleExample.prototype.tags = function () { };
|
||||
return simpleExample;
|
||||
}());
|
||||
exports.circularReference = /** @class */ (function () {
|
||||
function C() {
|
||||
@@ -70,13 +70,13 @@ var FooItem = /** @class */ (function () {
|
||||
exports.FooItem = FooItem;
|
||||
function WithTags(Base) {
|
||||
return /** @class */ (function (_super) {
|
||||
__extends(class_2, _super);
|
||||
function class_2() {
|
||||
__extends(class_1, _super);
|
||||
function class_1() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
class_2.getTags = function () { };
|
||||
class_2.prototype.tags = function () { };
|
||||
return class_2;
|
||||
class_1.getTags = function () { };
|
||||
class_1.prototype.tags = function () { };
|
||||
return class_1;
|
||||
}(Base));
|
||||
}
|
||||
exports.WithTags = WithTags;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -3,7 +3,7 @@ tests/cases/compiler/implicitAnyFromCircularInference.ts(5,5): error TS2502: 'b'
|
||||
tests/cases/compiler/implicitAnyFromCircularInference.ts(6,5): error TS2502: 'c' is referenced directly or indirectly in its own type annotation.
|
||||
tests/cases/compiler/implicitAnyFromCircularInference.ts(9,5): error TS2502: 'd' is referenced directly or indirectly in its own type annotation.
|
||||
tests/cases/compiler/implicitAnyFromCircularInference.ts(14,10): error TS7023: 'g' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
|
||||
tests/cases/compiler/implicitAnyFromCircularInference.ts(17,10): error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
|
||||
tests/cases/compiler/implicitAnyFromCircularInference.ts(17,5): error TS7023: 'f1' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
|
||||
tests/cases/compiler/implicitAnyFromCircularInference.ts(22,10): error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
|
||||
tests/cases/compiler/implicitAnyFromCircularInference.ts(25,10): error TS7023: 'h' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
|
||||
tests/cases/compiler/implicitAnyFromCircularInference.ts(27,14): error TS7023: 'foo' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
|
||||
@@ -38,8 +38,8 @@ tests/cases/compiler/implicitAnyFromCircularInference.ts(45,9): error TS7023: 'x
|
||||
|
||||
// Error expected
|
||||
var f1 = function () {
|
||||
~~~~~~~~
|
||||
!!! error TS7024: Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
|
||||
~~
|
||||
!!! error TS7023: 'f1' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
|
||||
return f1();
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
(async () => {
|
||||
const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString());
|
||||
>response : Symbol(response, Decl(example.ts, 2, 7))
|
||||
>fetch : Symbol(fetch, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
|
||||
>fetch : Symbol(fetch, Decl(lib.dom.d.ts, --, --))
|
||||
>new URL("../hamsters.jpg", import.meta.url).toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --))
|
||||
>URL : Symbol(URL, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
|
||||
>toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
>response : Response
|
||||
>await fetch(new URL("../hamsters.jpg", import.meta.url).toString()) : Response
|
||||
>fetch(new URL("../hamsters.jpg", import.meta.url).toString()) : Promise<Response>
|
||||
>fetch : { (input: RequestInfo, init?: RequestInit): Promise<Response>; (input: RequestInfo, init?: RequestInit): Promise<Response>; }
|
||||
>fetch : (input: RequestInfo, init?: RequestInit) => Promise<Response>
|
||||
>new URL("../hamsters.jpg", import.meta.url).toString() : string
|
||||
>new URL("../hamsters.jpg", import.meta.url).toString : () => string
|
||||
>new URL("../hamsters.jpg", import.meta.url) : URL
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
(async () => {
|
||||
const response = await fetch(new URL("../hamsters.jpg", import.meta.url).toString());
|
||||
>response : Symbol(response, Decl(example.ts, 2, 7))
|
||||
>fetch : Symbol(fetch, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
|
||||
>fetch : Symbol(fetch, Decl(lib.dom.d.ts, --, --))
|
||||
>new URL("../hamsters.jpg", import.meta.url).toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --))
|
||||
>URL : Symbol(URL, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
|
||||
>toString : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
>response : Response
|
||||
>await fetch(new URL("../hamsters.jpg", import.meta.url).toString()) : Response
|
||||
>fetch(new URL("../hamsters.jpg", import.meta.url).toString()) : Promise<Response>
|
||||
>fetch : { (input: RequestInfo, init?: RequestInit): Promise<Response>; (input: RequestInfo, init?: RequestInit): Promise<Response>; }
|
||||
>fetch : (input: RequestInfo, init?: RequestInit) => Promise<Response>
|
||||
>new URL("../hamsters.jpg", import.meta.url).toString() : string
|
||||
>new URL("../hamsters.jpg", import.meta.url).toString : () => string
|
||||
>new URL("../hamsters.jpg", import.meta.url) : URL
|
||||
|
||||
@@ -10,7 +10,7 @@ tests/cases/compiler/intersectionsOfLargeUnions2.ts(31,15): error TS2536: Type '
|
||||
interface ElementTagNameMap {
|
||||
~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2300: Duplicate identifier 'ElementTagNameMap'.
|
||||
!!! related TS6203 /.ts/lib.dom.d.ts:18110:6: 'ElementTagNameMap' was also declared here.
|
||||
!!! related TS6203 /.ts/lib.dom.d.ts:18325:6: 'ElementTagNameMap' was also declared here.
|
||||
[index: number]: HTMLElement
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
=== tests/cases/compiler/multiExtendsSplitInterfaces1.ts ===
|
||||
self.cancelAnimationFrame(0);
|
||||
>self.cancelAnimationFrame : Symbol(Window.cancelAnimationFrame, Decl(lib.dom.d.ts, --, --))
|
||||
>self.cancelAnimationFrame : Symbol(AnimationFrameProvider.cancelAnimationFrame, Decl(lib.dom.d.ts, --, --))
|
||||
>self : Symbol(self, Decl(lib.dom.d.ts, --, --))
|
||||
>cancelAnimationFrame : Symbol(Window.cancelAnimationFrame, Decl(lib.dom.d.ts, --, --))
|
||||
>cancelAnimationFrame : Symbol(AnimationFrameProvider.cancelAnimationFrame, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
|
||||
@@ -78,8 +78,8 @@ function f1() {
|
||||
var g = _newTarget;
|
||||
var h = function () { return _newTarget; };
|
||||
}
|
||||
var f2 = function _b() {
|
||||
var _newTarget = this && this instanceof _b ? this.constructor : void 0;
|
||||
var f2 = function f2() {
|
||||
var _newTarget = this && this instanceof f2 ? this.constructor : void 0;
|
||||
var i = _newTarget;
|
||||
var j = function () { return _newTarget; };
|
||||
};
|
||||
|
||||
@@ -265,63 +265,63 @@ var StaticName_Anonymous = /** @class */ (function () {
|
||||
return class_1;
|
||||
}());
|
||||
var StaticNameFn_Anonymous = /** @class */ (function () {
|
||||
function class_2() {
|
||||
function StaticNameFn_Anonymous() {
|
||||
}
|
||||
class_2.name = function () { }; // error
|
||||
class_2.prototype.name = function () { }; // ok
|
||||
return class_2;
|
||||
StaticNameFn_Anonymous.name = function () { }; // error
|
||||
StaticNameFn_Anonymous.prototype.name = function () { }; // ok
|
||||
return StaticNameFn_Anonymous;
|
||||
}());
|
||||
// length
|
||||
var StaticLength_Anonymous = /** @class */ (function () {
|
||||
function class_2() {
|
||||
}
|
||||
return class_2;
|
||||
}());
|
||||
var StaticLengthFn_Anonymous = /** @class */ (function () {
|
||||
function StaticLengthFn_Anonymous() {
|
||||
}
|
||||
StaticLengthFn_Anonymous.length = function () { }; // error
|
||||
StaticLengthFn_Anonymous.prototype.length = function () { }; // ok
|
||||
return StaticLengthFn_Anonymous;
|
||||
}());
|
||||
// prototype
|
||||
var StaticPrototype_Anonymous = /** @class */ (function () {
|
||||
function class_3() {
|
||||
}
|
||||
return class_3;
|
||||
}());
|
||||
var StaticLengthFn_Anonymous = /** @class */ (function () {
|
||||
var StaticPrototypeFn_Anonymous = /** @class */ (function () {
|
||||
function StaticPrototypeFn_Anonymous() {
|
||||
}
|
||||
StaticPrototypeFn_Anonymous.prototype = function () { }; // error
|
||||
StaticPrototypeFn_Anonymous.prototype.prototype = function () { }; // ok
|
||||
return StaticPrototypeFn_Anonymous;
|
||||
}());
|
||||
// caller
|
||||
var StaticCaller_Anonymous = /** @class */ (function () {
|
||||
function class_4() {
|
||||
}
|
||||
class_4.length = function () { }; // error
|
||||
class_4.prototype.length = function () { }; // ok
|
||||
return class_4;
|
||||
}());
|
||||
// prototype
|
||||
var StaticPrototype_Anonymous = /** @class */ (function () {
|
||||
var StaticCallerFn_Anonymous = /** @class */ (function () {
|
||||
function StaticCallerFn_Anonymous() {
|
||||
}
|
||||
StaticCallerFn_Anonymous.caller = function () { }; // error
|
||||
StaticCallerFn_Anonymous.prototype.caller = function () { }; // ok
|
||||
return StaticCallerFn_Anonymous;
|
||||
}());
|
||||
// arguments
|
||||
var StaticArguments_Anonymous = /** @class */ (function () {
|
||||
function class_5() {
|
||||
}
|
||||
return class_5;
|
||||
}());
|
||||
var StaticPrototypeFn_Anonymous = /** @class */ (function () {
|
||||
function class_6() {
|
||||
}
|
||||
class_6.prototype = function () { }; // error
|
||||
class_6.prototype.prototype = function () { }; // ok
|
||||
return class_6;
|
||||
}());
|
||||
// caller
|
||||
var StaticCaller_Anonymous = /** @class */ (function () {
|
||||
function class_7() {
|
||||
}
|
||||
return class_7;
|
||||
}());
|
||||
var StaticCallerFn_Anonymous = /** @class */ (function () {
|
||||
function class_8() {
|
||||
}
|
||||
class_8.caller = function () { }; // error
|
||||
class_8.prototype.caller = function () { }; // ok
|
||||
return class_8;
|
||||
}());
|
||||
// arguments
|
||||
var StaticArguments_Anonymous = /** @class */ (function () {
|
||||
function class_9() {
|
||||
}
|
||||
return class_9;
|
||||
}());
|
||||
var StaticArgumentsFn_Anonymous = /** @class */ (function () {
|
||||
function class_10() {
|
||||
function StaticArgumentsFn_Anonymous() {
|
||||
}
|
||||
class_10.arguments = function () { }; // error
|
||||
class_10.prototype.arguments = function () { }; // ok
|
||||
return class_10;
|
||||
StaticArgumentsFn_Anonymous.arguments = function () { }; // error
|
||||
StaticArgumentsFn_Anonymous.prototype.arguments = function () { }; // ok
|
||||
return StaticArgumentsFn_Anonymous;
|
||||
}());
|
||||
// === Static properties on default exported classes ===
|
||||
// name
|
||||
|
||||
@@ -45,11 +45,11 @@ var B = /** @class */ (function (_super) {
|
||||
function B() {
|
||||
var _this = this;
|
||||
var D = /** @class */ (function (_super) {
|
||||
__extends(class_1, _super);
|
||||
function class_1() {
|
||||
__extends(D, _super);
|
||||
function D() {
|
||||
return _super.call(this) || this;
|
||||
}
|
||||
return class_1;
|
||||
return D;
|
||||
}(C));
|
||||
return _this;
|
||||
}
|
||||
|
||||
@@ -4,13 +4,12 @@
|
||||
////declare module "jquery";
|
||||
|
||||
// @Filename: user.ts
|
||||
////import {[|{| "isWriteAccess": true, "isDefinition": true |}x|]} from "jquery";
|
||||
////[|import {[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}x|]} from "jquery";|]
|
||||
|
||||
// @Filename: user2.ts
|
||||
////import {[|{| "isWriteAccess": true, "isDefinition": true |}x|]} from "jquery";
|
||||
////[|import {[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}x|]} from "jquery";|]
|
||||
|
||||
const ranges = test.ranges();
|
||||
const [r0, r1] = ranges;
|
||||
const [r0Def, r0, r1Def, r1] = test.ranges();
|
||||
// TODO: Want these to be in the same group, but that would require creating a symbol for `x`.
|
||||
verify.singleReferenceGroup("(alias) module \"jquery\"\nimport x", [r0]);
|
||||
verify.singleReferenceGroup("(alias) module \"jquery\"\nimport x", [r1]);
|
||||
@@ -7,9 +7,9 @@
|
||||
////
|
||||
//// }
|
||||
////
|
||||
//// public /**/[|{| "isWriteAccess": true, "isDefinition": true |}start|](){
|
||||
//// [|public /**/[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}start|](){
|
||||
//// return this;
|
||||
//// }
|
||||
//// }|]
|
||||
////
|
||||
//// public stop(){
|
||||
//// return this;
|
||||
@@ -33,5 +33,5 @@ cancellation.resetCancelled();
|
||||
checkRefs();
|
||||
|
||||
function checkRefs() {
|
||||
verify.singleReferenceGroup("(method) Test.start(): this");
|
||||
verify.singleReferenceGroup("(method) Test.start(): this", "start");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitThis: true
|
||||
//// function returnThisMember([| |]) {
|
||||
//// return this.member;
|
||||
//// }
|
||||
////
|
||||
//// const container: any = {
|
||||
//// member: "sample",
|
||||
//// returnThisMember: returnThisMember,
|
||||
//// };
|
||||
////
|
||||
//// container.returnThisMember();
|
||||
|
||||
verify.codeFix({
|
||||
description: "Infer 'this' type of 'returnThisMember' from usage",
|
||||
index: 0,
|
||||
newRangeContent: "this: any ",
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitThis: true
|
||||
//// const returnThisMember = function ([| |]) {
|
||||
//// return this.member;
|
||||
//// }
|
||||
////
|
||||
//// interface Container {
|
||||
//// member: string;
|
||||
//// returnThisMember(): string;
|
||||
//// }
|
||||
////
|
||||
//// const container: Container = {
|
||||
//// member: "sample",
|
||||
//// returnThisMember: returnThisMember,
|
||||
//// };
|
||||
|
||||
verify.codeFix({
|
||||
description: "Infer 'this' type of 'returnThisMember' from usage",
|
||||
index: 0,
|
||||
newRangeContent: "this: Container ",
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitThis: true
|
||||
////function returnThisMember([| |]) {
|
||||
//// return this.member;
|
||||
//// }
|
||||
////
|
||||
//// interface Container {
|
||||
//// member: string;
|
||||
//// returnThisMember(): string;
|
||||
//// }
|
||||
////
|
||||
//// let container;
|
||||
//// container = {
|
||||
//// member: "sample",
|
||||
//// returnThisMember: returnThisMember,
|
||||
//// };
|
||||
////
|
||||
//// container.returnThisMember();
|
||||
|
||||
verify.codeFix({
|
||||
description: "Infer 'this' type of 'returnThisMember' from usage",
|
||||
index: 0,
|
||||
newRangeContent: "this: { member: string; returnThisMember: () => any; } ",
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noImplicitThis: true
|
||||
|
||||
// @Filename: /consumesType.js
|
||||
/////**
|
||||
//// * @returns {string}
|
||||
//// */
|
||||
////function [|returnThisMember|]() {
|
||||
//// return this.member;
|
||||
////}
|
||||
////
|
||||
////class Container {
|
||||
//// member = "sample";
|
||||
//// returnThisMember = returnThisMember;
|
||||
////};
|
||||
////
|
||||
////container.returnThisMember();
|
||||
|
||||
verify.codeFix({
|
||||
description: "Infer 'this' type of 'returnThisMember' from usage",
|
||||
index: 0,
|
||||
newFileContent: `/**
|
||||
* @returns {string}
|
||||
* @this {Container}
|
||||
*/
|
||||
function returnThisMember() {
|
||||
return this.member;
|
||||
}
|
||||
|
||||
class Container {
|
||||
member = "sample";
|
||||
returnThisMember = returnThisMember;
|
||||
};
|
||||
|
||||
container.returnThisMember();`
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noImplicitThis: true
|
||||
|
||||
// @Filename: /consumesType.js
|
||||
////function [|returnThisMember|]() {
|
||||
//// return this.member;
|
||||
////}
|
||||
////
|
||||
////class Container {
|
||||
//// member = "sample";
|
||||
//// returnThisMember = returnThisMember;
|
||||
////};
|
||||
////
|
||||
////container.returnThisMember();
|
||||
|
||||
verify.codeFix({
|
||||
description: "Infer 'this' type of 'returnThisMember' from usage",
|
||||
index: 0,
|
||||
newFileContent: `/**
|
||||
* @this {Container}
|
||||
*/
|
||||
function returnThisMember() {
|
||||
return this.member;
|
||||
}
|
||||
|
||||
class Container {
|
||||
member = "sample";
|
||||
returnThisMember = returnThisMember;
|
||||
};
|
||||
|
||||
container.returnThisMember();`
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noImplicitThis: true
|
||||
|
||||
// @Filename: /consumesType.js
|
||||
////function [|returnThisMember|]() {
|
||||
//// return this.member;
|
||||
////}
|
||||
////
|
||||
/////**
|
||||
//// * @type {import("/providesType").Container}
|
||||
//// */
|
||||
////const container = {
|
||||
//// member: "sample",
|
||||
//// returnThisMember: returnThisMember,
|
||||
////};
|
||||
////
|
||||
////container.returnThisMember();
|
||||
|
||||
// @Filename: /providesType.ts
|
||||
////interface Container {
|
||||
//// member: string;
|
||||
//// returnThisMember(): string;
|
||||
////}
|
||||
|
||||
verify.codeFix({
|
||||
description: "Infer 'this' type of 'returnThisMember' from usage",
|
||||
index: 0,
|
||||
newFileContent: `/**
|
||||
* @this {any}
|
||||
*/
|
||||
function returnThisMember() {
|
||||
return this.member;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {import("/providesType").Container}
|
||||
*/
|
||||
const container = {
|
||||
member: "sample",
|
||||
returnThisMember: returnThisMember,
|
||||
};
|
||||
|
||||
container.returnThisMember();`
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noImplicitThis: true
|
||||
|
||||
// @Filename: /consumesType.js
|
||||
////function [|returnThisMember|]() {
|
||||
//// return this.member;
|
||||
////}
|
||||
////
|
||||
////const container = {
|
||||
//// member: "sample",
|
||||
//// returnThisMember: returnThisMember,
|
||||
////};
|
||||
////
|
||||
////container.returnThisMember();
|
||||
|
||||
verify.codeFix({
|
||||
description: "Infer 'this' type of 'returnThisMember' from usage",
|
||||
index: 0,
|
||||
newFileContent: `/**
|
||||
* @this {{ member: string; returnThisMember: () => any; }}
|
||||
*/
|
||||
function returnThisMember() {
|
||||
return this.member;
|
||||
}
|
||||
|
||||
const container = {
|
||||
member: "sample",
|
||||
returnThisMember: returnThisMember,
|
||||
};
|
||||
|
||||
container.returnThisMember();`
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitThis: true
|
||||
////function returnThisMember([| |]) {
|
||||
//// return this.member;
|
||||
//// }
|
||||
////
|
||||
//// const container = {
|
||||
//// member: "sample",
|
||||
//// returnThisMember: returnThisMember,
|
||||
//// };
|
||||
|
||||
verify.codeFix({
|
||||
description: "Infer 'this' type of 'returnThisMember' from usage",
|
||||
index: 0,
|
||||
newRangeContent: "this: { member: string; returnThisMember: () => any; } ",
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitThis: true
|
||||
////function returnThisMember([| |]) {
|
||||
//// return this.member;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: "Infer 'this' type of 'returnThisMember' from usage",
|
||||
index: 0,
|
||||
newRangeContent: "this: any ",
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitThis: true
|
||||
////function returnThisMember([| |]) {
|
||||
//// return this.member;
|
||||
//// }
|
||||
////
|
||||
//// interface Container {
|
||||
//// member: string;
|
||||
//// returnThisMember(): string;
|
||||
//// }
|
||||
////
|
||||
//// const container: Container = {
|
||||
//// member: "sample",
|
||||
//// returnThisMember: returnThisMember,
|
||||
//// };
|
||||
////
|
||||
//// container.returnThisMember();
|
||||
|
||||
verify.rangeAfterCodeFix("this: Container");
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitThis: true
|
||||
////function returnThisMember([| |]suffix: string) {
|
||||
//// return this.member + suffix;
|
||||
//// }
|
||||
////
|
||||
//// interface Container {
|
||||
//// member: string;
|
||||
//// returnThisMember(suffix: string): string;
|
||||
//// }
|
||||
////
|
||||
//// const container: Container = {
|
||||
//// member: "sample",
|
||||
//// returnThisMember: returnThisMember,
|
||||
//// };
|
||||
////
|
||||
//// container.returnThisMember("");
|
||||
|
||||
verify.rangeAfterCodeFix("this: Container, ");
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitThis: true
|
||||
////function returnThisMember([| |]) {
|
||||
//// return this.member;
|
||||
//// }
|
||||
////
|
||||
//// interface Container {
|
||||
//// member: string;
|
||||
//// returnThisMember(): string;
|
||||
//// }
|
||||
////
|
||||
//// const container: Container = {
|
||||
//// member: "sample",
|
||||
//// returnThisMember,
|
||||
//// };
|
||||
////
|
||||
//// container.returnThisMember();
|
||||
|
||||
verify.rangeAfterCodeFix("this: Container");
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitThis: true
|
||||
////function returnThisMember([| |]suffix: string) {
|
||||
//// return this.member + suffix;
|
||||
//// }
|
||||
////
|
||||
//// interface Container {
|
||||
//// member: string;
|
||||
//// returnThisMember(suffix: string): string;
|
||||
//// }
|
||||
////
|
||||
//// const container: Container = {
|
||||
//// member: "sample",
|
||||
//// returnThisMember,
|
||||
//// };
|
||||
////
|
||||
//// container.returnThisMember("");
|
||||
|
||||
verify.rangeAfterCodeFix("this: Container, ");
|
||||
@@ -1,12 +1,12 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @Filename: fileA.ts
|
||||
//// export function [|__foo|]() {
|
||||
//// }
|
||||
//// [|export function [|{| "contextRangeIndex": 0 |}__foo|]() {
|
||||
//// }|]
|
||||
////
|
||||
// @Filename: fileB.ts
|
||||
//// import { [|__foo|] as bar } from "./fileA";
|
||||
//// [|import { [|{| "contextRangeIndex": 2 |}__foo|] as bar } from "./fileA";|]
|
||||
////
|
||||
//// bar();
|
||||
|
||||
verify.rangesAreRenameLocations();
|
||||
verify.rangesWithSameTextAreRenameLocations("__foo");
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
// @noImplicitReferences: true
|
||||
|
||||
// @Filename: /node_modules/a/index.d.ts
|
||||
////import [|{| "name": "useAX", "isWriteAccess": true, "isDefinition": true |}X|] from "x";
|
||||
////[|import [|{| "name": "useAX", "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}X|] from "x";|]
|
||||
////export function a(x: [|X|]): void;
|
||||
|
||||
// @Filename: /node_modules/a/node_modules/x/index.d.ts
|
||||
////export default class /*defAX*/[|{| "isWriteAccess": true, "isDefinition": true |}X|] {
|
||||
////[|export default class /*defAX*/[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 3 |}X|] {
|
||||
//// private x: number;
|
||||
////}
|
||||
////}|]
|
||||
|
||||
// @Filename: /node_modules/a/node_modules/x/package.json
|
||||
////{ "name": "x", "version": "1.2.3" }
|
||||
|
||||
// @Filename: /node_modules/b/index.d.ts
|
||||
////import [|{| "name": "useBX", "isWriteAccess": true, "isDefinition": true |}X|] from "x";
|
||||
////[|import [|{| "name": "useBX", "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 5 |}X|] from "x";|]
|
||||
////export const b: [|X|];
|
||||
|
||||
// @Filename: /node_modules/b/node_modules/x/index.d.ts
|
||||
////export default class /*defBX*/[|{| "isWriteAccess": true, "isDefinition": true |}X|] {
|
||||
////[|export default class /*defBX*/[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 8 |}X|] {
|
||||
//// private x: number;
|
||||
////}
|
||||
////}|]
|
||||
|
||||
// @Filename: /node_modules/b/node_modules/x/package.json
|
||||
////{ "name": "x", "version": "1.2.3" }
|
||||
@@ -35,7 +35,7 @@ verify.numberOfErrorsInCurrentFile(0);
|
||||
verify.goToDefinition("useAX", "defAX");
|
||||
verify.goToDefinition("useBX", "defAX");
|
||||
|
||||
const [r0, r1, r2, r3, r4, r5] = test.ranges();
|
||||
const [r0Def, r0, r1, r2Def, r2, r3Def, r3, r4, r5Def, r5] = test.ranges();
|
||||
const aImport = { definition: "(alias) class X\nimport X", ranges: [r0, r1] };
|
||||
const def = { definition: "class X", ranges: [r2] };
|
||||
const bImport = { definition: "(alias) class X\nimport X", ranges: [r3, r4] };
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
// @Filename: /abc.d.ts
|
||||
////declare module "a" {
|
||||
//// export const [|{| "isWriteAccess": true, "isDefinition": true |}x|]: number;
|
||||
//// [|export const [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}x|]: number;|]
|
||||
////}
|
||||
|
||||
// @Filename: /b.ts
|
||||
////import a from "a";
|
||||
////a.[|x|];
|
||||
|
||||
verify.singleReferenceGroup("const x: number");
|
||||
verify.singleReferenceGroup("const x: number", "x");
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
|
||||
// @Filename: /a.d.ts
|
||||
////export as namespace abc;
|
||||
////export const [|{| "isWriteAccess": true, "isDefinition": true |}x|]: number;
|
||||
////[|export const [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}x|]: number;|]
|
||||
|
||||
// @Filename: /b.ts
|
||||
////import a from "./a";
|
||||
////a.[|x|];
|
||||
|
||||
verify.singleReferenceGroup('const x: number');
|
||||
verify.singleReferenceGroup('const x: number', "x");
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
//// class B {}
|
||||
//// function foo() {
|
||||
//// return {[|{| "isWriteAccess": true, "isDefinition": true |}B|]: B};
|
||||
//// return {[|[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}B|]: B|]};
|
||||
//// }
|
||||
//// class C extends (foo()).[|B|] {}
|
||||
//// class C1 extends foo().[|B|] {}
|
||||
|
||||
verify.singleReferenceGroup("(property) B: typeof B");
|
||||
verify.singleReferenceGroup("(property) B: typeof B", "B");
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// @Filename: foo.ts
|
||||
//// export function foo() { return "foo"; }
|
||||
|
||||
//// import("[|./foo|]")
|
||||
//// var x = import("[|./foo|]")
|
||||
//// [|import("[|{| "contextRangeIndex": 0 |}./foo|]")|]
|
||||
//// [|var x = import("[|{| "contextRangeIndex": 2 |}./foo|]")|]
|
||||
|
||||
verify.singleReferenceGroup('module "/tests/cases/fourslash/foo"');
|
||||
verify.singleReferenceGroup('module "/tests/cases/fourslash/foo"', "./foo");
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: foo.ts
|
||||
//// export function [|{| "isWriteAccess": true, "isDefinition": true |}bar|]() { return "bar"; }
|
||||
//// [|export function [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}bar|]() { return "bar"; }|]
|
||||
|
||||
//// var x = import("./foo");
|
||||
//// x.then(foo => {
|
||||
//// foo.[|bar|]();
|
||||
//// })
|
||||
|
||||
verify.singleReferenceGroup("function bar(): string");
|
||||
verify.rangesAreRenameLocations();
|
||||
verify.singleReferenceGroup("function bar(): string", "bar");
|
||||
verify.rangesWithSameTextAreRenameLocations("bar");
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: foo.ts
|
||||
////export function [|{| "isWriteAccess": true, "isDefinition": true |}bar|]() { return "bar"; }
|
||||
////import('./foo').then(({ [|{| "isWriteAccess": true, "isDefinition": true |}bar|] }) => undefined);
|
||||
////[|export function [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}bar|]() { return "bar"; }|]
|
||||
////import('./foo').then(([|{ [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}bar|] }|]) => undefined);
|
||||
|
||||
const [r0, r1] = test.ranges();
|
||||
const [r0Def, r0, r1Def, r1] = test.ranges();
|
||||
verify.referenceGroups(r0, [{ definition: "function bar(): string", ranges: [r0, r1] }]);
|
||||
verify.referenceGroups(r1, [
|
||||
{ definition: "function bar(): string", ranges: [r0] },
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
///<reference path="fourslash.ts" />
|
||||
// @allowJs: true
|
||||
// @Filename: Foo.js
|
||||
/////** @type {function ([|{|"isWriteAccess": true, "isDefinition": true|}new|]: string, string): string} */
|
||||
/////** @type {function ([|[|{|"isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0|}new|]: string|], string): string} */
|
||||
////var f;
|
||||
|
||||
const [a0] = test.ranges();
|
||||
const [a0Def, a0] = test.ranges();
|
||||
verify.singleReferenceGroup("(parameter) new: string", [a0]);
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
// @Filename: a.ts
|
||||
////export class C {
|
||||
//// [|constructor|](n: number);
|
||||
//// [|constructor|]();
|
||||
//// [|constructor|](n?: number){}
|
||||
//// [|[|{| "contextRangeIndex": 0 |}constructor|](n: number);|]
|
||||
//// [|[|{| "contextRangeIndex": 2 |}constructor|]();|]
|
||||
//// [|[|{| "contextRangeIndex": 4 |}constructor|](n?: number){}|]
|
||||
//// static f() {
|
||||
//// this.f();
|
||||
//// new [|this|]();
|
||||
@@ -40,8 +40,7 @@
|
||||
////new a.[|C|]();
|
||||
////class d extends a.C { constructor() { [|super|](); }
|
||||
|
||||
const ranges = test.ranges();
|
||||
const [a0, a1, a2, a3, a4, b0, c0, d0, d1] = ranges;
|
||||
const [a0Def, a0, a1Def, a1, a2Def, a2, a3, a4, b0, c0, d0, d1] = test.ranges();
|
||||
verify.referenceGroups([a0, a2], defs("class C"));
|
||||
verify.referenceGroups(a1, defs("class C"));
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////class C {
|
||||
//// [|constructor|](n: number);
|
||||
//// [|constructor|](){}
|
||||
//// [|[|{| "contextRangeIndex": 0 |}constructor|](n: number);|]
|
||||
//// [|[|{| "contextRangeIndex": 2 |}constructor|](){}|]
|
||||
////}
|
||||
|
||||
verify.singleReferenceGroup("class C");
|
||||
verify.singleReferenceGroup("class C", "constructor");
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
// @esModuleInterop: true
|
||||
|
||||
// @Filename: /foo.ts
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}settings|] from "./settings.json";
|
||||
////[|import [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}settings|] from "./settings.json";|]
|
||||
////[|settings|];
|
||||
|
||||
// @Filename: /settings.json
|
||||
//// {}
|
||||
|
||||
verify.singleReferenceGroup("import settings");
|
||||
verify.singleReferenceGroup("import settings", "settings");
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
|
||||
// @Filename: /node_modules/@types/three/index.d.ts
|
||||
////export * from "./three-core";
|
||||
////export as namespace [|{| "isWriteAccess": true, "isDefinition": true |}THREE|];
|
||||
////[|export as namespace [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}THREE|];|]
|
||||
|
||||
// @Filename: /typings/global.d.ts
|
||||
////import * as _THREE from '[|three|]';
|
||||
////[|import * as _THREE from '[|{| "contextRangeIndex": 2 |}three|]';|]
|
||||
////declare global {
|
||||
//// const [|{| "isWriteAccess": true, "isDefinition": true |}THREE|]: typeof _THREE;
|
||||
//// [|const [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 4 |}THREE|]: typeof _THREE;|]
|
||||
////}
|
||||
|
||||
// @Filename: /src/index.ts
|
||||
@@ -38,7 +38,8 @@
|
||||
//// "files": ["/src/index.ts", "typings/global.d.ts"]
|
||||
////}
|
||||
|
||||
const [r0Def, r0, r1Def, r1, r2Def, ...rest] = test.ranges();
|
||||
// GH#29533
|
||||
// TODO:: this should be var THREE: typeof import instead of module name as var but thats existing issue and repros with quickInfo too.
|
||||
verify.singleReferenceGroup(`module "/node_modules/@types/three/index"
|
||||
var "/node_modules/@types/three/index": typeof import("/node_modules/@types/three/index")`);
|
||||
var "/node_modules/@types/three/index": typeof import("/node_modules/@types/three/index")`, [r0, r1, ...rest]);
|
||||
@@ -1,7 +1,7 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////import { [|ab|] as [|{| "isWriteAccess": true, "isDefinition": true |}cd|] } from "doesNotExist";
|
||||
////[|import { [|{| "contextRangeIndex": 0 |}ab|] as [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}cd|] } from "doesNotExist";|]
|
||||
|
||||
const [r0, r1] = test.ranges();
|
||||
const [r0Def, r0, r1] = test.ranges();
|
||||
verify.referenceGroups(r0, undefined);
|
||||
verify.singleReferenceGroup("import cd", [r1]);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////export = class [|{| "isWriteAccess": true, "isDefinition": true |}A|] {
|
||||
////export = [|class [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}A|] {
|
||||
//// m() { [|A|]; }
|
||||
////};
|
||||
////}|];
|
||||
|
||||
// @Filename: /b.ts
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}A|] = require("./a");
|
||||
////[|import [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 3 |}A|] = require("./a");|]
|
||||
////[|A|];
|
||||
|
||||
const [r0, r1, r2, r3] = test.ranges();
|
||||
const [r0Def, r0, r1, r2Def, r2, r3] = test.ranges();
|
||||
const defs = { definition: "(local class) A", ranges: [r0, r1] };
|
||||
const imports = { definition: '(alias) (local class) A\nimport A = require("./a")', ranges: [r2, r3] };
|
||||
verify.referenceGroups([r0, r1], [defs, imports]);
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
// @allowJs: true
|
||||
|
||||
// @Filename: /a.js
|
||||
////module.exports = class [|{| "isWriteAccess": true, "isDefinition": true |}A|] {};
|
||||
////module.exports = [|class [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}A|] {}|];
|
||||
|
||||
// @Filename: /b.js
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}A|] = require("./a");
|
||||
////[|import [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}A|] = require("./a");|]
|
||||
////[|A|];
|
||||
|
||||
const [r0, r1, r2] = test.ranges();
|
||||
const [r0Def, r0, r1Def, r1, r2] = test.ranges();
|
||||
const defs = { definition: "(local class) A", ranges: [r0] };
|
||||
const imports = { definition: '(alias) (local class) A\nimport A = require("./a")', ranges: [r1, r2] };
|
||||
verify.referenceGroups([r0], [defs, imports]);
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
// @allowJs: true
|
||||
|
||||
// @Filename: /a.js
|
||||
////exports.[|{| "isWriteAccess": true, "isDefinition": true |}A|] = class {};
|
||||
////[|exports.[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}A|] = class {};|]
|
||||
|
||||
// @Filename: /b.js
|
||||
////import { [|{| "isWriteAccess": true, "isDefinition": true |}A|] } from "./a";
|
||||
////[|import { [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}A|] } from "./a";|]
|
||||
////[|A|];
|
||||
|
||||
const [r0, r1, r2] = test.ranges();
|
||||
const [r0Def, r0, r1Def, r1, r2] = test.ranges();
|
||||
const defs = { definition: "class A\n(property) A: typeof A", ranges: [r0] };
|
||||
const imports = { definition: "(alias) class A\n(alias) (property) A: typeof A\nimport A", ranges: [r1, r2] };
|
||||
verify.referenceGroups([r0], [defs, imports]);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////class [|{| "isWriteAccess": true, "isDefinition": true |}C|] {
|
||||
////[|class [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}C|] {
|
||||
//// static s() {
|
||||
//// [|this|];
|
||||
//// }
|
||||
@@ -10,9 +10,9 @@
|
||||
//// function inner() { this; }
|
||||
//// class Inner { x = this; }
|
||||
//// }
|
||||
////}
|
||||
////}|]
|
||||
|
||||
const [r0, r1, r2] = test.ranges();
|
||||
const [r0Def, r0, r1, r2] = test.ranges();
|
||||
verify.referenceGroups(r0, [{ definition: "class C", ranges: [r0, r1, r2] }]);
|
||||
verify.singleReferenceGroup("this: typeof C", [r1, r2]);
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
// @Filename: /a.js
|
||||
////function f() {
|
||||
//// this.[|{| "isWriteAccess": true, "isDefinition": true |}x|] = 0;
|
||||
//// [|this.[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}x|] = 0;|]
|
||||
////}
|
||||
////f.prototype.setX = function() {
|
||||
//// this.[|{| "isWriteAccess": true, "isDefinition": true |}x|] = 1;
|
||||
//// [|this.[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}x|] = 1;|]
|
||||
////}
|
||||
////f.prototype.useX = function() { this.[|x|]; }
|
||||
|
||||
verify.singleReferenceGroup("(property) f.x: number");
|
||||
verify.singleReferenceGroup("(property) f.x: number", "x");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////declare class [|{| "isWriteAccess": true, "isDefinition": true |}C|] {
|
||||
////[|declare class [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}C|] {
|
||||
//// static m(): void;
|
||||
////}
|
||||
////}|]
|
||||
|
||||
verify.singleReferenceGroup("class C");
|
||||
verify.singleReferenceGroup("class C", "C");
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////export default function [|{| "isWriteAccess": true, "isDefinition": true |}a|]() {}
|
||||
////[|export default function [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}a|]() {}|]
|
||||
|
||||
// @Filename: /b.ts
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}a|], * as ns from "./a";
|
||||
////[|import [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}a|], * as ns from "./a";|]
|
||||
|
||||
const [r0, r1] = test.ranges();
|
||||
const [r0Def, r0, r1Def, r1] = test.ranges();
|
||||
const a: FourSlashInterface.ReferenceGroup = { definition: "function a(): void", ranges: [r0] };
|
||||
const b: FourSlashInterface.ReferenceGroup = { definition: "(alias) function a(): void\nimport a", ranges: [r1] };
|
||||
verify.referenceGroups(r0, [a, b]);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////export [|{| "isWriteAccess": true, "isDefinition": true |}default|] function [|{| "isWriteAccess": true, "isDefinition": true |}f|]() {}
|
||||
////[|export [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}default|] function [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}f|]() {}|]
|
||||
|
||||
// @Filename: /b.ts
|
||||
////export import a = require("./a");
|
||||
@@ -10,10 +10,10 @@
|
||||
////import { a } from "./b";
|
||||
////a.[|default|]();
|
||||
////
|
||||
////declare const x: { [|{| "isWriteAccess": true, "isDefinition": true |}default|]: number };
|
||||
////declare const x: { [|[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 4 |}default|]: number|] };
|
||||
////x.[|default|];
|
||||
|
||||
const [r0, r1, r2, r3, r4] = test.ranges();
|
||||
const [r0Def, r0, r1, r2, r3Def, r3, r4] = test.ranges();
|
||||
|
||||
verify.referenceGroups([r0], [{ definition: "function f(): void", ranges: [r0, r2] }]);
|
||||
verify.singleReferenceGroup("function f(): void", [r1, r2]);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////const [|{| "isWriteAccess": true, "isDefinition": true |}x|] = 0;
|
||||
////[|const [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}x|] = 0;|]
|
||||
////[|x|];
|
||||
|
||||
const ranges = test.ranges();
|
||||
const ranges = test.rangesByText().get("x");
|
||||
verify.referenceGroups(ranges, [
|
||||
{
|
||||
definition: { text: "const x: 0", range: ranges[0] },
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////interface I<T> {
|
||||
//// [|{| "isDefinition": true |}x|]: boolean;
|
||||
//// [|[|{| "isDefinition": true, "contextRangeIndex": 0 |}x|]: boolean;|]
|
||||
////}
|
||||
////declare const i: I<number>;
|
||||
////const { [|{| "isWriteAccess": true, "isDefinition": true |}x|] } = i;
|
||||
////[|const { [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}x|] } = i;|]
|
||||
|
||||
const [r0, r1] = test.ranges();
|
||||
const [r0Def, r0, r1Def, r1] = test.ranges();
|
||||
|
||||
verify.referenceGroups(r0, [{ definition: "(property) I<T>.x: boolean", ranges: [r0, r1] }]);
|
||||
verify.referenceGroups(r1, [
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////class Test {
|
||||
//// get [|{| "isDefinition": true, "isWriteAccess": true |}x|]() { return 0; }
|
||||
//// [|get [|{| "isDefinition": true, "isWriteAccess": true, "contextRangeIndex": 0 |}x|]() { return 0; }|]
|
||||
////
|
||||
//// set [|{| "isDefinition": true, "isWriteAccess": true |}y|](a: number) {}
|
||||
//// [|set [|{| "isDefinition": true, "isWriteAccess": true, "contextRangeIndex": 2 |}y|](a: number) {}|]
|
||||
////}
|
||||
////const { [|{| "isDefinition": true, "isWriteAccess": true |}x|], [|{| "isDefinition": true, "isWriteAccess": true |}y|] } = new Test();
|
||||
////[|const { [|{| "isDefinition": true, "isWriteAccess": true, "contextRangeIndex": 4 |}x|], [|{| "isDefinition": true, "isWriteAccess": true, "contextRangeIndex": 4 |}y|] } = new Test();|]
|
||||
////[|x|]; [|y|];
|
||||
|
||||
const [x0, y0, x1, y1, x2, y2] = test.ranges();
|
||||
const [x0Def, x0, y0Def, y0, xy1Def, x1, y1, x2, y2] = test.ranges();
|
||||
verify.referenceGroups(x0, [{ definition: "(property) Test.x: number", ranges: [x0, x1] }]);
|
||||
verify.referenceGroups(x1, [
|
||||
{ definition: "(property) Test.x: number", ranges: [x0] },
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
// @Filename: /a.ts
|
||||
////class C {
|
||||
//// get [|{| "isWriteAccess": true, "isDefinition": true |}g|](): number { return 0; }
|
||||
//// [|get [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}g|](): number { return 0; }|]
|
||||
////
|
||||
//// set [|{| "isWriteAccess": true, "isDefinition": true |}s|](value: number) {}
|
||||
//// [|set [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}s|](value: number) {}|]
|
||||
////}
|
||||
////const { [|{| "isWriteAccess": true, "isDefinition": true |}g|], [|{| "isWriteAccess": true, "isDefinition": true |}s|] } = new C();
|
||||
////[|const { [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 4 |}g|], [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 4 |}s|] } = new C();|]
|
||||
|
||||
const [g0, s0, g1, s1] = test.ranges();
|
||||
const [g0Def, g0, s0Def, s0, gs1Def, g1, s1] = test.ranges();
|
||||
verify.quickInfoAt(g0, "(property) C.g: number");
|
||||
verify.referenceGroups(g0, [{ definition: "(property) C.g: number", ranges: [g0, g1] }]);
|
||||
verify.referenceGroups(g1, [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////enum [|{| "isWriteAccess": true, "isDefinition": true |}E|] { A }
|
||||
////[|enum [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}E|] { A }|]
|
||||
////let e: [|E|].A;
|
||||
|
||||
verify.singleReferenceGroup("enum E");
|
||||
verify.singleReferenceGroup("enum E", "E");
|
||||
|
||||
@@ -3,19 +3,18 @@
|
||||
// `export as namespace` results in global search.
|
||||
|
||||
// @Filename: /node_modules/a/index.d.ts
|
||||
////export function [|{| "isWriteAccess": true, "isDefinition": true |}f|](): void;
|
||||
////[|export function [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}f|](): void;|]
|
||||
////export as namespace A;
|
||||
|
||||
// @Filename: /b.ts
|
||||
////import { [|{| "isWriteAccess": true, "isDefinition": true |}f|] } from "a";
|
||||
////[|import { [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}f|] } from "a";|]
|
||||
|
||||
// @Filename: /c.ts
|
||||
////A.[|f|]();
|
||||
|
||||
verify.noErrors();
|
||||
|
||||
const ranges = test.ranges();
|
||||
const [r0, r1, r2] = ranges;
|
||||
const [r0Def, r0, r1Def, r1, r2] = test.ranges();
|
||||
|
||||
const globals = { definition: "function f(): void", ranges: [r0, r2] };
|
||||
const imports = { definition: "(alias) function f(): void\nimport f", ranges: [r1] };
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////class [|{| "isWriteAccess": true, "isDefinition": true |}C|] {}
|
||||
////export const [|{| "isWriteAccess": true, "isDefinition": true |}D|] = [|C|];
|
||||
////[|class [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}C|] {}|]
|
||||
////[|export const [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}D|] = [|C|];|]
|
||||
|
||||
// @Filename: /b.ts
|
||||
////import { [|{| "isWriteAccess": true, "isDefinition": true |}D|] } from "./a";
|
||||
////[|import { [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 5 |}D|] } from "./a";|]
|
||||
|
||||
const [C0, D0, C1, D1] = test.ranges();
|
||||
const [C0Def, C0, D0Def, D0, C1, D1Def, D1] = test.ranges();
|
||||
|
||||
verify.singleReferenceGroup("class C", [C0, C1]);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
////export default class {
|
||||
//// [|constructor|]() {}
|
||||
//// [|[|{| "contextRangeIndex": 0 |}constructor|]() {}|]
|
||||
////}
|
||||
|
||||
verify.singleReferenceGroup("class default");
|
||||
verify.singleReferenceGroup("class default", "constructor");
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////type [|{| "isWriteAccess": true, "isDefinition": true |}T|] = number;
|
||||
////[|export|] = [|T|];
|
||||
////[|type [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}T|] = number;|]
|
||||
////[|[|{| "contextRangeIndex": 2 |}export|] = [|{| "contextRangeIndex": 2 |}T|];|]
|
||||
|
||||
// @Filename: /b.ts
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}T|] = require("[|./a|]");
|
||||
////[|import [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 5 |}T|] = require("[|{| "contextRangeIndex": 5 |}./a|]");|]
|
||||
|
||||
const [r0, r1, r2, r3, r4] = test.ranges();
|
||||
const [r0Def, r0, r12Def, r1, r2, r3Def, r3, r4] = test.ranges();
|
||||
const mod = { definition: 'module "/a"', ranges: [r4, r1] };
|
||||
const a = { definition: "type T = number", ranges: [r0, r2] };
|
||||
const b = { definition: '(alias) type T = number\nimport T = require("./a")', ranges: [r3] };
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////{
|
||||
//// export const [|{| "isWriteAccess": true, "isDefinition": true |}x|] = 0;
|
||||
//// [|export const [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}x|] = 0;|]
|
||||
//// [|x|];
|
||||
////}
|
||||
|
||||
verify.singleReferenceGroup("const x: 0");
|
||||
verify.singleReferenceGroup("const x: 0", "x");
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface I {
|
||||
//// ["[|{| "isDefinition": true |}prop1|]"]: () => void;
|
||||
//// [|["[|{| "isDefinition": true, "contextRangeIndex": 0 |}prop1|]"]: () => void;|]
|
||||
////}
|
||||
////
|
||||
////class C implements I {
|
||||
//// ["[|{| "isDefinition": true |}prop1|]"]: any;
|
||||
//// [|["[|{| "isDefinition": true, "contextRangeIndex": 2 |}prop1|]"]: any;|]
|
||||
////}
|
||||
////
|
||||
////var x: I = {
|
||||
//// ["[|{| "isWriteAccess": true, "isDefinition": true |}prop1|]"]: function () { },
|
||||
//// [|["[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 4 |}prop1|]"]: function () { }|],
|
||||
////}
|
||||
|
||||
const ranges = test.ranges();
|
||||
const [r0, r1, r2] = ranges;
|
||||
verify.referenceGroups(ranges, [
|
||||
const [r0Def, r0, r1Def, r1, r2Def, r2] = test.ranges();
|
||||
verify.referenceGroups([r0, r1, r2], [
|
||||
{ definition: { text: '(property) I["prop1"]: () => void', range: r0 }, ranges: [r0, r2] },
|
||||
{ definition: { text: '(property) C["prop1"]: any', range: r1 }, ranges: [r1] },
|
||||
]);
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface I {
|
||||
//// [[|{| "isDefinition": true |}42|]](): void;
|
||||
//// [|[[|{| "isDefinition": true, "contextRangeIndex": 0 |}42|]](): void;|]
|
||||
////}
|
||||
////
|
||||
////class C implements I {
|
||||
//// [[|{| "isDefinition": true |}42|]]: any;
|
||||
//// [|[[|{| "isDefinition": true, "contextRangeIndex": 2 |}42|]]: any;|]
|
||||
////}
|
||||
////
|
||||
////var x: I = {
|
||||
//// ["[|{| "isWriteAccess": true, "isDefinition": true |}42|]"]: function () { }
|
||||
//// [|["[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 4 |}42|]"]: function () { }|]
|
||||
////}
|
||||
|
||||
const ranges = test.ranges();
|
||||
const [r0, r1, r2] = ranges;
|
||||
verify.referenceGroups(ranges, [
|
||||
const [r0Def, r0, r1Def, r1, r2Def, r2] = test.ranges();
|
||||
verify.referenceGroups([r0, r1, r2], [
|
||||
{ definition: { text: '(method) I[42](): void', range: r0 }, ranges: [r0, r2] },
|
||||
{ definition: { text: '(property) C[42]: any', range: r1 }, ranges: [r1] },
|
||||
]);
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @Filename: a.ts
|
||||
////export default function /*def*/[|{| "isWriteAccess": true, "isDefinition": true |}f|]() {}
|
||||
////[|export default function /*def*/[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}f|]() {}|]
|
||||
|
||||
// @Filename: b.ts
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}g|] from "./a";
|
||||
////[|import [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}g|] from "./a";|]
|
||||
////[|/*ref*/g|]();
|
||||
|
||||
// @Filename: c.ts
|
||||
////import { f } from "./a";
|
||||
|
||||
const ranges = test.ranges();
|
||||
const [r0, r1, r2] = ranges;
|
||||
const [r0Def, r0, r1Def, r1, r2] = test.ranges();
|
||||
verify.referenceGroups(r0, [
|
||||
{ definition: "function f(): void", ranges: [r0] },
|
||||
{ definition: "(alias) function g(): void\nimport g", ranges: [r1, r2] }
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////export default class [|{| "isWriteAccess": true, "isDefinition": true |}DefaultExportedClass|] {
|
||||
////}
|
||||
////[|export default class [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}DefaultExportedClass|] {
|
||||
////}|]
|
||||
////
|
||||
////var x: [|DefaultExportedClass|];
|
||||
////
|
||||
////var y = new [|DefaultExportedClass|];
|
||||
|
||||
verify.singleReferenceGroup("class DefaultExportedClass");
|
||||
verify.singleReferenceGroup("class DefaultExportedClass", "DefaultExportedClass");
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////export default function [|{| "isWriteAccess": true, "isDefinition": true |}DefaultExportedFunction|]() {
|
||||
////[|export default function [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}DefaultExportedFunction|]() {
|
||||
//// return [|DefaultExportedFunction|];
|
||||
////}
|
||||
////}|]
|
||||
////
|
||||
////var x: typeof [|DefaultExportedFunction|];
|
||||
////
|
||||
////var y = [|DefaultExportedFunction|]();
|
||||
////
|
||||
////namespace [|{| "isWriteAccess": true, "isDefinition": true |}DefaultExportedFunction|] {
|
||||
////}
|
||||
////[|namespace [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 5 |}DefaultExportedFunction|] {
|
||||
////}|]
|
||||
|
||||
|
||||
const ranges = test.ranges();
|
||||
const [r0, r1, r2, r3, r4] = ranges;
|
||||
const [r0Def, r0, r1, r2, r3, r4Def, r4] = test.ranges();
|
||||
const fnRanges = [r0, r1, r2, r3];
|
||||
verify.singleReferenceGroup("function DefaultExportedFunction(): () => typeof DefaultExportedFunction", fnRanges);
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////function [|{| "isWriteAccess": true, "isDefinition": true |}f|]() {
|
||||
////[|function [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}f|]() {
|
||||
//// return 100;
|
||||
////}
|
||||
////}|]
|
||||
////
|
||||
////export default [|f|];
|
||||
////[|export default [|{| "contextRangeIndex": 2 |}f|];|]
|
||||
////
|
||||
////var x: typeof [|f|];
|
||||
////
|
||||
////var y = [|f|]();
|
||||
////
|
||||
////namespace [|{| "isWriteAccess": true, "isDefinition": true |}f|] {
|
||||
////[|namespace [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 6 |}f|] {
|
||||
//// var local = 100;
|
||||
////}
|
||||
////}|]
|
||||
|
||||
verify.singleReferenceGroup("namespace f\nfunction f(): number");
|
||||
verify.singleReferenceGroup("namespace f\nfunction f(): number", "f");
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////const [|{| "isWriteAccess": true, "isDefinition": true |}a|] = 0;
|
||||
////export [|{| "isWriteAccess": true, "isDefinition": true |}default|] [|a|];
|
||||
////[|const [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}a|] = 0;|]
|
||||
////[|export [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}default|] [|{| "contextRangeIndex": 2 |}a|];|]
|
||||
|
||||
// @Filename: /b.ts
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}a|] from "./a";
|
||||
////[|import [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 5 |}a|] from "./a";|]
|
||||
////[|a|];
|
||||
|
||||
const [r0, r1, r2, r3, r4] = test.ranges();
|
||||
const [r0Def, r0, r1Def, r1, r2, r3Def, r3, r4] = test.ranges();
|
||||
verify.referenceGroups([r0, r2], [
|
||||
{ definition: "const a: 0", ranges: [r0, r2] },
|
||||
{ definition: "(alias) const a: 0\nimport a", ranges: [r3, r4] }
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
////
|
||||
////var y = new DefaultExportedClass;
|
||||
////
|
||||
////namespace [|{| "isWriteAccess": true, "isDefinition": true |}DefaultExportedClass|] {
|
||||
////}
|
||||
////[|namespace [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}DefaultExportedClass|] {
|
||||
////}|]
|
||||
|
||||
verify.noErrors();
|
||||
|
||||
// The namespace and class do not merge,
|
||||
// so the namespace should be all alone.
|
||||
verify.singleReferenceGroup("class DefaultExportedClass\nnamespace DefaultExportedClass");
|
||||
verify.singleReferenceGroup("class DefaultExportedClass\nnamespace DefaultExportedClass", "DefaultExportedClass");
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////export [|{| "isWriteAccess": true, "isDefinition": true |}default|] function() {}
|
||||
////[|export [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}default|] function() {}|]
|
||||
|
||||
// @Filename: /b.ts
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}f|] from "./a";
|
||||
////[|import [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}f|] from "./a";|]
|
||||
|
||||
const [r0, r1] = test.ranges();
|
||||
const [r0Def, r0, r1Def, r1] = test.ranges();
|
||||
verify.referenceGroups(r0, [
|
||||
{ definition: "function default(): void", ranges: [r0] },
|
||||
{ definition: "import f", ranges: [r1] },
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////export [|{| "isDefinition": true, "isWriteAccess": true |}default|] 1;
|
||||
////[|export [|{| "isDefinition": true, "isWriteAccess": true, "contextRangeIndex": 0 |}default|] 1;|]
|
||||
|
||||
// @Filename: /b.ts
|
||||
////import [|{| "isDefinition": true, "isWriteAccess": true |}a|] from "./a";
|
||||
////[|import [|{| "isDefinition": true, "isWriteAccess": true, "contextRangeIndex": 2 |}a|] from "./a";|]
|
||||
|
||||
const [r0, r1] = test.ranges();
|
||||
const [r0Def, r0, r1Def, r1] = test.ranges();
|
||||
verify.referenceGroups(r0, [
|
||||
{ definition: "(property) default: 1", ranges: [r0] },
|
||||
{ definition: "import a", ranges: [r1] },
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: /export.ts
|
||||
////const [|{| "isWriteAccess": true, "isDefinition": true |}foo|] = 1;
|
||||
////export default [|foo|];
|
||||
////[|const [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}foo|] = 1;|]
|
||||
////[|export default [|{| "contextRangeIndex": 2 |}foo|];|]
|
||||
|
||||
// @Filename: /re-export.ts
|
||||
////export { [|{| "isWriteAccess": true, "isDefinition": true |}default|] } from "./export";
|
||||
////[|export { [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 4 |}default|] } from "./export";|]
|
||||
|
||||
// @Filename: /re-export-dep.ts
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}fooDefault|] from "./re-export";
|
||||
////[|import [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 6 |}fooDefault|] from "./re-export";|]
|
||||
|
||||
const [r0, r1, r2, r3] = test.ranges();
|
||||
const [r0Def, r0, r1Def, r1, r2Def, r2, r3Def, r3] = test.ranges();
|
||||
verify.referenceGroups([r0, r1], [
|
||||
{ definition: "const foo: 1", ranges: [r0, r1] },
|
||||
{ definition: "(alias) const foo: 1\nexport default", ranges: [r2], },
|
||||
|
||||
+5
-5
@@ -3,18 +3,18 @@
|
||||
// @allowSyntheticDefaultImports: true
|
||||
|
||||
// @Filename: /export.ts
|
||||
////const [|{| "isWriteAccess": true, "isDefinition": true |}foo|] = 1;
|
||||
////export = [|foo|];
|
||||
////[|const [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}foo|] = 1;|]
|
||||
////[|export = [|{| "contextRangeIndex": 2 |}foo|];|]
|
||||
|
||||
// @Filename: /re-export.ts
|
||||
////export { [|{| "isWriteAccess": true, "isDefinition": true |}default|] } from "./export";
|
||||
////[|export { [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 4 |}default|] } from "./export";|]
|
||||
|
||||
// @Filename: /re-export-dep.ts
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}fooDefault|] from "./re-export";
|
||||
////[|import [|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 6 |}fooDefault|] from "./re-export";|]
|
||||
|
||||
verify.noErrors();
|
||||
|
||||
const [r0, r1, r2, r3] = test.ranges();
|
||||
const [r0Def, r0, r1Def, r1, r2Def, r2, r3Def, r3] = test.ranges();
|
||||
verify.referenceGroups([r0, r1], [
|
||||
{ definition: "const foo: 1", ranges: [r0, r1] },
|
||||
{ definition: "(alias) const foo: 1\nexport default", ranges: [r2], },
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user