mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add test infrastructure
This commit is contained in:
+21
-1
@@ -300,7 +300,7 @@ namespace ts.server {
|
||||
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan {
|
||||
const args: protocol.FileLocationRequestArgs = this.createFileLocationRequestArgs(fileName, position);
|
||||
|
||||
const request = this.processRequest<protocol.DefinitionRequest>(CommandNames.DefinitionAndBoundSpan, args);
|
||||
const request = this.processRequest<protocol.DefinitionAndBoundSpanRequest>(CommandNames.DefinitionAndBoundSpan, args);
|
||||
const response = this.processResponse<protocol.DefinitionInfoAndBoundSpanResponse>(request);
|
||||
const body = Debug.checkDefined(response.body); // TODO: GH#18217
|
||||
|
||||
@@ -334,6 +334,26 @@ namespace ts.server {
|
||||
}));
|
||||
}
|
||||
|
||||
getSourceDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan {
|
||||
const args: protocol.FileLocationRequestArgs = this.createFileLocationRequestArgs(fileName, position);
|
||||
const request = this.processRequest<protocol.SourceDefinitionAndBoundSpanRequest>(CommandNames.SourceDefinitionAndBoundSpan, args);
|
||||
const response = this.processResponse<protocol.DefinitionInfoAndBoundSpanResponse>(request);
|
||||
const body = Debug.checkDefined(response.body); // TODO: GH#18217
|
||||
|
||||
return {
|
||||
definitions: body.definitions.map(entry => ({
|
||||
containerKind: ScriptElementKind.unknown,
|
||||
containerName: "",
|
||||
fileName: entry.file,
|
||||
textSpan: this.decodeSpan(entry),
|
||||
kind: ScriptElementKind.unknown,
|
||||
name: "",
|
||||
unverified: entry.unverified,
|
||||
})),
|
||||
textSpan: this.decodeSpan(body.textSpan, request.arguments.file)
|
||||
};
|
||||
}
|
||||
|
||||
getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] {
|
||||
const args = this.createFileLocationRequestArgs(fileName, position);
|
||||
|
||||
|
||||
@@ -697,6 +697,13 @@ namespace FourSlash {
|
||||
this.verifyGoToX(arg0, endMarkerNames, () => this.getGoToDefinitionAndBoundSpan());
|
||||
}
|
||||
|
||||
public verifyGoToSourceDefinition(startMarkerNames: ArrayOrSingle<string>, end?: ArrayOrSingle<string | { marker: string, unverified?: boolean }> | { file: string, unverified?: boolean }) {
|
||||
if (this.testType !== FourSlashTestType.Server) {
|
||||
this.raiseError("goToSourceDefinition may only be used in fourslash/server tests.");
|
||||
}
|
||||
this.verifyGoToX(startMarkerNames, end, () => (this.languageService as ts.server.SessionClient).getSourceDefinitionAndBoundSpan(this.activeFile.fileName, this.currentCaretPosition)!);
|
||||
}
|
||||
|
||||
private getGoToDefinition(): readonly ts.DefinitionInfo[] {
|
||||
return this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition)!;
|
||||
}
|
||||
|
||||
@@ -324,6 +324,10 @@ namespace FourSlashInterface {
|
||||
this.state.verifyGoToType(arg0, endMarkerName);
|
||||
}
|
||||
|
||||
public goToSourceDefinition(startMarkerNames: ArrayOrSingle<string>, end: { file: string } | ArrayOrSingle<string>) {
|
||||
this.state.verifyGoToSourceDefinition(startMarkerNames, end);
|
||||
}
|
||||
|
||||
public goToDefinitionForMarkers(...markerNames: string[]) {
|
||||
this.state.verifyGoToDefinitionForMarkers(markerNames);
|
||||
}
|
||||
|
||||
@@ -83,6 +83,9 @@ namespace ts.server.protocol {
|
||||
SignatureHelp = "signatureHelp",
|
||||
/* @internal */
|
||||
SignatureHelpFull = "signatureHelp-full",
|
||||
SourceDefinitionAndBoundSpan = "sourceDefinitionAndBoundSpan",
|
||||
/* @internal */
|
||||
SourceDefinitionAndBoundSpanFull = "sourceDefinitionAndBoundSpan-full",
|
||||
Status = "status",
|
||||
TypeDefinition = "typeDefinition",
|
||||
ProjectInfo = "projectInfo",
|
||||
@@ -904,6 +907,10 @@ namespace ts.server.protocol {
|
||||
readonly command: CommandTypes.DefinitionAndBoundSpan;
|
||||
}
|
||||
|
||||
export interface SourceDefinitionAndBoundSpanRequest extends FileLocationRequest {
|
||||
readonly command: CommandTypes.SourceDefinitionAndBoundSpan;
|
||||
}
|
||||
|
||||
export interface DefinitionAndBoundSpanResponse extends Response {
|
||||
readonly body: DefinitionInfoAndBoundSpan;
|
||||
}
|
||||
|
||||
+47
-64
@@ -1239,36 +1239,6 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
private getDefinitionAndBoundSpan(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.DefinitionInfoAndBoundSpan | DefinitionInfoAndBoundSpan {
|
||||
// const { file, project } = this.getFileAndProject(args);
|
||||
// const position = this.getPositionInFile(args, file);
|
||||
// const scriptInfo = Debug.checkDefined(project.getScriptInfo(file));
|
||||
|
||||
// const unmappedDefinitionAndBoundSpan = project.getLanguageService().getDefinitionAndBoundSpan(file, position);
|
||||
|
||||
// if (!unmappedDefinitionAndBoundSpan || !unmappedDefinitionAndBoundSpan.definitions) {
|
||||
// return {
|
||||
// definitions: emptyArray,
|
||||
// textSpan: undefined! // TODO: GH#18217
|
||||
// };
|
||||
// }
|
||||
|
||||
// const definitions = this.mapDefinitionInfoLocations(unmappedDefinitionAndBoundSpan.definitions, project);
|
||||
// const { textSpan } = unmappedDefinitionAndBoundSpan;
|
||||
|
||||
// if (simplifiedResult) {
|
||||
// return {
|
||||
// definitions: this.mapDefinitionInfo(definitions, project),
|
||||
// textSpan: toProtocolTextSpan(textSpan, scriptInfo)
|
||||
// };
|
||||
// }
|
||||
|
||||
// return {
|
||||
// definitions: definitions.map(Session.mapToOriginalLocation),
|
||||
// textSpan,
|
||||
// };
|
||||
// }
|
||||
|
||||
// private getSourceDefinitionAndBoundSpan(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.DefinitionInfoAndBoundSpan | DefinitionInfoAndBoundSpan {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
const scriptInfo = Debug.checkDefined(project.getScriptInfo(file));
|
||||
@@ -1282,17 +1252,7 @@ namespace ts.server {
|
||||
};
|
||||
}
|
||||
|
||||
const definitions = this.mapDefinitionInfoLocations(unmappedDefinitionAndBoundSpan.definitions, project).slice();
|
||||
const needsJsResolution = every(definitions.filter(d => d.isAliasTarget), d => !!d.isAmbient);
|
||||
if (needsJsResolution) {
|
||||
project.withAuxiliaryProjectForFiles([file], auxiliaryProject => {
|
||||
const jsDefinitions = auxiliaryProject.getLanguageService().getDefinitionAndBoundSpan(file, position);
|
||||
for (const jsDefinition of jsDefinitions?.definitions || emptyArray) {
|
||||
pushIfUnique(definitions, jsDefinition, (a, b) => a.fileName === b.fileName && a.textSpan.start === b.textSpan.start);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const definitions = this.mapDefinitionInfoLocations(unmappedDefinitionAndBoundSpan.definitions, project);
|
||||
const { textSpan } = unmappedDefinitionAndBoundSpan;
|
||||
|
||||
if (simplifiedResult) {
|
||||
@@ -1306,30 +1266,47 @@ namespace ts.server {
|
||||
definitions: definitions.map(Session.mapToOriginalLocation),
|
||||
textSpan,
|
||||
};
|
||||
}
|
||||
|
||||
// function getLocationsResolvingToDts(symbol: Symbol, checker: TypeChecker) {
|
||||
// let locations: DocumentPosition[] | undefined;
|
||||
// while (symbol.flags & SymbolFlags.Alias) {
|
||||
// const aliasDeclaration = find(symbol.declarations || emptyArray, isAliasSymbolDeclaration);
|
||||
// if (!aliasDeclaration) break;
|
||||
private getSourceDefinitionAndBoundSpan(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.DefinitionInfoAndBoundSpan | DefinitionInfoAndBoundSpan {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
const scriptInfo = Debug.checkDefined(project.getScriptInfo(file));
|
||||
|
||||
// const resolvedSymbol = checker.getImmediateAliasedSymbol(symbol);
|
||||
// if (!resolvedSymbol) break;
|
||||
const unmappedDefinitionAndBoundSpan = project.getLanguageService().getDefinitionAndBoundSpan(file, position);
|
||||
|
||||
// const hasUnmappedDtsDeclarations = some(resolvedSymbol.declarations, d => {
|
||||
// const sourceFile = getSourceFileOfNode(d);
|
||||
// if (!isDeclarationFileName(sourceFile.fileName)) return false;
|
||||
// const mappedFileName = project.getSourceMapper().tryGetSourcePosition(sourceFile)?.fileName;
|
||||
// if (mappedFileName && project.projectService.fileExists(toNormalizedPath(mappedFileName))) return false;
|
||||
// });
|
||||
// if (hasUnmappedDtsDeclarations) {
|
||||
// const sourceFile = getSourceFileOfNode(aliasDeclaration);
|
||||
// locations = append(locations, { fileName: sourceFile.fileName, pos: aliasDeclaration.getStart(sourceFile) });
|
||||
// }
|
||||
// symbol = resolvedSymbol;
|
||||
// }
|
||||
// return locations;
|
||||
// }
|
||||
if (!unmappedDefinitionAndBoundSpan || !unmappedDefinitionAndBoundSpan.definitions) {
|
||||
return {
|
||||
definitions: emptyArray,
|
||||
textSpan: undefined! // TODO: GH#18217
|
||||
};
|
||||
}
|
||||
|
||||
let definitions = this.mapDefinitionInfoLocations(unmappedDefinitionAndBoundSpan.definitions, project).slice();
|
||||
const needsJsResolution = every(definitions.filter(d => d.isAliasTarget), d => !!d.isAmbient);
|
||||
if (needsJsResolution) {
|
||||
project.withAuxiliaryProjectForFiles([file], auxiliaryProject => {
|
||||
const jsDefinitions = auxiliaryProject.getLanguageService().getDefinitionAndBoundSpan(file, position);
|
||||
for (const jsDefinition of jsDefinitions?.definitions || emptyArray) {
|
||||
pushIfUnique(definitions, jsDefinition, (a, b) => a.fileName === b.fileName && a.textSpan.start === b.textSpan.start);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
definitions = definitions.filter(d => !d.isAmbient);
|
||||
const { textSpan } = unmappedDefinitionAndBoundSpan;
|
||||
|
||||
if (simplifiedResult) {
|
||||
return {
|
||||
definitions: this.mapDefinitionInfo(definitions, project),
|
||||
textSpan: toProtocolTextSpan(textSpan, scriptInfo)
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
definitions: definitions.map(Session.mapToOriginalLocation),
|
||||
textSpan,
|
||||
};
|
||||
}
|
||||
|
||||
private getEmitOutput(args: protocol.EmitOutputRequestArgs): EmitOutput | protocol.EmitOutput {
|
||||
@@ -2750,12 +2727,18 @@ namespace ts.server {
|
||||
[CommandNames.DefinitionFull]: (request: protocol.DefinitionRequest) => {
|
||||
return this.requiredResponse(this.getDefinition(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.DefinitionAndBoundSpan]: (request: protocol.DefinitionRequest) => {
|
||||
[CommandNames.DefinitionAndBoundSpan]: (request: protocol.DefinitionAndBoundSpanRequest) => {
|
||||
return this.requiredResponse(this.getDefinitionAndBoundSpan(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.DefinitionAndBoundSpanFull]: (request: protocol.DefinitionRequest) => {
|
||||
[CommandNames.DefinitionAndBoundSpanFull]: (request: protocol.DefinitionAndBoundSpanRequest) => {
|
||||
return this.requiredResponse(this.getDefinitionAndBoundSpan(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.SourceDefinitionAndBoundSpan]: (request: protocol.SourceDefinitionAndBoundSpanRequest) => {
|
||||
return this.requiredResponse(this.getSourceDefinitionAndBoundSpan(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.SourceDefinitionAndBoundSpanFull]: (request: protocol.SourceDefinitionAndBoundSpanRequest) => {
|
||||
return this.requiredResponse(this.getSourceDefinitionAndBoundSpan(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.EmitOutput]: (request: protocol.EmitOutputRequest) => {
|
||||
return this.requiredResponse(this.getEmitOutput(request.arguments));
|
||||
},
|
||||
|
||||
@@ -317,6 +317,8 @@ declare namespace FourSlashInterface {
|
||||
goToDefinition(startsAndEnds: { [startMarkerName: string]: ArrayOrSingle<string> }): void;
|
||||
/** Verifies goToDefinition for each `${markerName}Reference` -> `${markerName}Definition` */
|
||||
goToDefinitionForMarkers(...markerNames: string[]): void;
|
||||
goToSourceDefinition(startMarkerNames: ArrayOrSingle<string>, fileResult: { file: string }): void;
|
||||
goToSourceDefinition(startMarkerNames: ArrayOrSingle<string>, endMarkerNames: ArrayOrSingle<string>): void;
|
||||
goToType(startsAndEnds: { [startMarkerName: string]: ArrayOrSingle<string> }): void;
|
||||
goToType(startMarkerNames: ArrayOrSingle<string>, endMarkerNames: ArrayOrSingle<string>): void;
|
||||
verifyGetEmitOutputForCurrentFile(expected: string): void;
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/// <reference path="../fourslash.ts" />
|
||||
|
||||
// @Filename: /a.js
|
||||
//// export const /*end*/a = "a";
|
||||
|
||||
// @Filename: /a.d.ts
|
||||
//// export declare const a: string;
|
||||
|
||||
// @Filename: /index.ts
|
||||
//// import { a } from "./a";
|
||||
//// [|a/*start*/|]
|
||||
|
||||
verify.goToSourceDefinition("start", "end");
|
||||
Reference in New Issue
Block a user