Merge branch 'master' into report-multiple-overload-errors

This commit is contained in:
Nathan Shively-Sanders
2019-06-19 10:46:51 -07:00
393 changed files with 5186 additions and 3792 deletions
+1
View File
@@ -0,0 +1 @@
--install.no-lockfile true
+4 -1
View File
@@ -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
+7
View File
@@ -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");
+3
View File
@@ -5187,6 +5187,9 @@ namespace ts {
return node.parent.left.name;
}
}
else if (isVariableDeclaration(node.parent) && isIdentifier(node.parent.name)) {
return node.parent.name;
}
}
/**
+9 -2
View File
@@ -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
View File
@@ -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[] }) {
+2018 -1804
View File
File diff suppressed because it is too large Load Diff
+94 -30
View File
@@ -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;
}
+395 -319
View File
File diff suppressed because it is too large Load Diff
+16 -8
View File
@@ -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
View File
@@ -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 {
+100 -10
View File
@@ -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;
}
+196 -23
View File
@@ -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;
}
+8 -2
View File
@@ -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)
)
};
}
+19 -9
View File
@@ -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 },
+13
View File
@@ -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);
+8
View File
@@ -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;
}
+2 -2
View File
@@ -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"
})
],
},
],
});
+62 -7
View File
@@ -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] }
]
}
};
+95 -15
View File
@@ -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 };",
}),
],
},
],
+15 -3
View File
@@ -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
View File
@@ -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;
+7
View File
@@ -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();
};
+1 -1
View File
@@ -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, --, --))
+1 -1
View File
@@ -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, --, --))
+2 -2
View File
@@ -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");
@@ -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], },
@@ -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