mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
navigateTo: Collect results from all referenced projects. (#25283)
* navigateTo: Collect results from all referenced projects. * Don't use project references, just source maps * Move more code to session * Test when implementation file is deleted * Use tsserver tests instead of fourslash tests to ensure session is used * Support find-all-references * Restore fourslash tests * Update emit baselines (added missing newline) * Support rename * @weswigham code review * Don't open/close files * Avoid growing `toDo` too eagerly * @sheetalkamat code review * Also get symlinked projects for originalLocation * Update API (#24966) * More @sheetalkamat code review * Remove unnecessary test * Update API (#24966)
This commit is contained in:
@@ -7655,7 +7655,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function isDeclarationFileName(fileName: string): boolean {
|
||||
/** @internal */
|
||||
export function isDeclarationFileName(fileName: string): boolean {
|
||||
return fileExtensionIs(fileName, Extension.Dts);
|
||||
}
|
||||
|
||||
|
||||
@@ -2344,7 +2344,7 @@ namespace ts {
|
||||
const refPath = resolveProjectReferencePath(host, ref);
|
||||
// An absolute path pointing to the containing directory of the config file
|
||||
const basePath = getNormalizedAbsolutePath(getDirectoryPath(refPath), host.getCurrentDirectory());
|
||||
const sourceFile = host.getSourceFile(refPath, ScriptTarget.JSON) as JsonSourceFile;
|
||||
const sourceFile = host.getSourceFile(refPath, ScriptTarget.JSON) as JsonSourceFile | undefined;
|
||||
if (sourceFile === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -2823,10 +2823,14 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
export interface ResolveProjectReferencePathHost {
|
||||
fileExists(fileName: string): boolean;
|
||||
}
|
||||
/**
|
||||
* Returns the target config filename of a project reference
|
||||
* Returns the target config filename of a project reference.
|
||||
* Note: The file might not exist.
|
||||
*/
|
||||
export function resolveProjectReferencePath(host: CompilerHost | UpToDateHost, ref: ProjectReference): ResolvedConfigFileName {
|
||||
export function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName {
|
||||
if (!host.fileExists(ref.path)) {
|
||||
return combinePaths(ref.path, "tsconfig.json") as ResolvedConfigFileName;
|
||||
}
|
||||
|
||||
+11
-11
@@ -215,17 +215,6 @@ namespace ts {
|
||||
sourceMapDataList = undefined!;
|
||||
}
|
||||
|
||||
interface SourceMapSection {
|
||||
version: 3;
|
||||
file: string;
|
||||
sourceRoot?: string;
|
||||
sources: string[];
|
||||
names?: string[];
|
||||
mappings: string;
|
||||
sourcesContent?: (string | null)[];
|
||||
sections?: undefined;
|
||||
}
|
||||
|
||||
type SourceMapSectionDefinition =
|
||||
| { offset: { line: number, column: number }, url: string } // Included for completeness
|
||||
| { offset: { line: number, column: number }, map: SourceMap };
|
||||
@@ -582,6 +571,17 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export interface SourceMapSection {
|
||||
version: 3;
|
||||
file: string;
|
||||
sourceRoot?: string;
|
||||
sources: string[];
|
||||
names?: string[];
|
||||
mappings: string;
|
||||
sourcesContent?: (string | null)[];
|
||||
sections?: undefined;
|
||||
}
|
||||
|
||||
const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
function base64FormatEncode(inValue: number) {
|
||||
|
||||
+12
-5
@@ -73,7 +73,7 @@ namespace ts.server {
|
||||
return { span: this.decodeSpan(codeEdit, fileName), newText: codeEdit.newText };
|
||||
}
|
||||
|
||||
private processRequest<T extends protocol.Request>(command: string, args?: T["arguments"]): T {
|
||||
private processRequest<T extends protocol.Request>(command: string, args: T["arguments"]): T {
|
||||
const request: protocol.Request = {
|
||||
seq: this.sequence,
|
||||
type: "request",
|
||||
@@ -278,9 +278,10 @@ namespace ts.server {
|
||||
|
||||
const request = this.processRequest<protocol.DefinitionRequest>(CommandNames.DefinitionAndBoundSpan, args);
|
||||
const response = this.processResponse<protocol.DefinitionInfoAndBoundSpanReponse>(request);
|
||||
const body = Debug.assertDefined(response.body); // TODO: GH#18217
|
||||
|
||||
return {
|
||||
definitions: response.body!.definitions.map(entry => ({ // TODO: GH#18217
|
||||
definitions: body.definitions.map(entry => ({
|
||||
containerKind: ScriptElementKind.unknown,
|
||||
containerName: "",
|
||||
fileName: entry.file,
|
||||
@@ -288,7 +289,7 @@ namespace ts.server {
|
||||
kind: ScriptElementKind.unknown,
|
||||
name: ""
|
||||
})),
|
||||
textSpan: this.decodeSpan(response.body!.textSpan, request.arguments.file)
|
||||
textSpan: this.decodeSpan(body.textSpan, request.arguments.file)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -341,8 +342,10 @@ namespace ts.server {
|
||||
}));
|
||||
}
|
||||
|
||||
getEmitOutput(_fileName: string): EmitOutput {
|
||||
return notImplemented();
|
||||
getEmitOutput(file: string): EmitOutput {
|
||||
const request = this.processRequest<protocol.EmitOutputRequest>(protocol.CommandTypes.EmitOutput, { file });
|
||||
const response = this.processResponse<protocol.EmitOutputResponse>(request);
|
||||
return response.body;
|
||||
}
|
||||
|
||||
getSyntacticDiagnostics(file: string): DiagnosticWithLocation[] {
|
||||
@@ -716,6 +719,10 @@ namespace ts.server {
|
||||
throw new Error("cleanupSemanticCache is not available through the server layer.");
|
||||
}
|
||||
|
||||
getSourceMapper(): never {
|
||||
return notImplemented();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
throw new Error("dispose is not available through the server layer.");
|
||||
}
|
||||
|
||||
+39
-25
@@ -1007,7 +1007,7 @@ namespace FourSlash {
|
||||
|
||||
// If any of the expected values are undefined, assume that users don't
|
||||
// care about them.
|
||||
if (replacementSpan && !TestState.textSpansEqual(replacementSpan, entry.replacementSpan)) {
|
||||
if (replacementSpan && !ts.textSpansEqual(replacementSpan, entry.replacementSpan)) {
|
||||
return false;
|
||||
}
|
||||
else if (expectedText && text !== expectedText) {
|
||||
@@ -1644,7 +1644,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
});
|
||||
}
|
||||
|
||||
public baselineGetEmitOutput(insertResultsIntoVfs?: boolean) {
|
||||
private getEmitFiles(): ReadonlyArray<FourSlashFile> {
|
||||
// Find file to be emitted
|
||||
const emitFiles: FourSlashFile[] = []; // List of FourSlashFile that has emitThisFile flag on
|
||||
|
||||
@@ -1661,12 +1661,29 @@ Actual: ${stringify(fullActual)}`);
|
||||
this.raiseError("No emitThisFile is specified in the test file");
|
||||
}
|
||||
|
||||
return emitFiles;
|
||||
}
|
||||
|
||||
public verifyGetEmitOutput(expectedOutputFiles: ReadonlyArray<string>): void {
|
||||
const outputFiles = ts.flatMap(this.getEmitFiles(), e => this.languageService.getEmitOutput(e.fileName).outputFiles);
|
||||
|
||||
assert.deepEqual(outputFiles.map(f => f.name), expectedOutputFiles);
|
||||
|
||||
for (const { name, text } of outputFiles) {
|
||||
const fromTestFile = this.getFileContent(name);
|
||||
if (fromTestFile !== text) {
|
||||
this.raiseError("Emit output is not as expected: " + showTextDiff(fromTestFile, text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public baselineGetEmitOutput(): void {
|
||||
Harness.Baseline.runBaseline(
|
||||
this.testData.globalOptions[MetadataOptionNames.baselineFile],
|
||||
ts.Debug.assertDefined(this.testData.globalOptions[MetadataOptionNames.baselineFile]),
|
||||
() => {
|
||||
let resultString = "";
|
||||
// Loop through all the emittedFiles and emit them one by one
|
||||
emitFiles.forEach(emitFile => {
|
||||
for (const emitFile of this.getEmitFiles()) {
|
||||
const emitOutput = this.languageService.getEmitOutput(emitFile.fileName);
|
||||
// Print emitOutputStatus in readable format
|
||||
resultString += "EmitSkipped: " + emitOutput.emitSkipped + Harness.IO.newLine();
|
||||
@@ -1692,13 +1709,10 @@ Actual: ${stringify(fullActual)}`);
|
||||
|
||||
for (const outputFile of emitOutput.outputFiles) {
|
||||
const fileName = "FileName : " + outputFile.name + Harness.IO.newLine();
|
||||
resultString = resultString + fileName + outputFile.text;
|
||||
if (insertResultsIntoVfs) {
|
||||
this.languageServiceAdapterHost.addScript(ts.getNormalizedAbsolutePath(outputFile.name, "/"), outputFile.text, /*isRootFile*/ true);
|
||||
}
|
||||
resultString = resultString + Harness.IO.newLine() + fileName + outputFile.text;
|
||||
}
|
||||
resultString += Harness.IO.newLine();
|
||||
});
|
||||
}
|
||||
|
||||
return resultString;
|
||||
});
|
||||
@@ -2137,11 +2151,10 @@ Actual: ${stringify(fullActual)}`);
|
||||
this.raiseError("verifyRangesInImplementationList failed - expected to find at least one implementation location but got 0");
|
||||
}
|
||||
|
||||
const duplicate = findDuplicatedElement(implementations, implementationsAreEqual);
|
||||
const duplicate = findDuplicatedElement(implementations, ts.documentSpansEqual);
|
||||
if (duplicate) {
|
||||
const { textSpan, fileName } = duplicate;
|
||||
const end = textSpan.start + textSpan.length;
|
||||
this.raiseError(`Duplicate implementations returned for range (${textSpan.start}, ${end}) in ${fileName}`);
|
||||
this.raiseError(`Duplicate implementations returned for range (${textSpan.start}, ${ts.textSpanEnd(textSpan)}) in ${fileName}`);
|
||||
}
|
||||
|
||||
const ranges = this.getRanges();
|
||||
@@ -2208,10 +2221,6 @@ Actual: ${stringify(fullActual)}`);
|
||||
this.raiseError(error);
|
||||
}
|
||||
|
||||
function implementationsAreEqual(a: ImplementationLocationInformation, b: ImplementationLocationInformation) {
|
||||
return a.fileName === b.fileName && TestState.textSpansEqual(a.textSpan, b.textSpan);
|
||||
}
|
||||
|
||||
function displayPartIsEqualTo(a: ts.SymbolDisplayPart, b: ts.SymbolDisplayPart): boolean {
|
||||
return a.kind === b.kind && a.text === b.text;
|
||||
}
|
||||
@@ -3260,7 +3269,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
|
||||
if (spanIndex !== undefined) {
|
||||
const span = this.getTextSpanForRangeAtIndex(spanIndex);
|
||||
assert.isTrue(TestState.textSpansEqual(span, item.replacementSpan), this.assertionMessageAtLastKnownMarker(stringify(span) + " does not equal " + stringify(item.replacementSpan) + " replacement span for " + stringify(entryId)));
|
||||
assert.isTrue(ts.textSpansEqual(span, item.replacementSpan), this.assertionMessageAtLastKnownMarker(stringify(span) + " does not equal " + stringify(item.replacementSpan) + " replacement span for " + stringify(entryId)));
|
||||
}
|
||||
|
||||
eq(item.hasAction, hasAction, "hasAction");
|
||||
@@ -3346,10 +3355,6 @@ Actual: ${stringify(fullActual)}`);
|
||||
this.cancellationToken.resetCancelled();
|
||||
}
|
||||
|
||||
private static textSpansEqual(a: ts.TextSpan | undefined, b: ts.TextSpan | undefined): boolean {
|
||||
return !!a && !!b && a.start === b.start && a.length === b.length;
|
||||
}
|
||||
|
||||
public getEditsForFileRename({ oldPath, newPath, newFileContents }: FourSlashInterface.GetEditsForFileRenameOptions): void {
|
||||
const test = (fileContents: { readonly [fileName: string]: string }, description: string): void => {
|
||||
const changes = this.languageService.getEditsForFileRename(oldPath, newPath, this.formatCodeSettings, ts.emptyOptions);
|
||||
@@ -3551,8 +3556,13 @@ ${code}
|
||||
|
||||
function getNonFileNameOptionInObject(optionObject: { [s: string]: string }): string | undefined {
|
||||
for (const option in optionObject) {
|
||||
if (option !== MetadataOptionNames.fileName) {
|
||||
return option;
|
||||
switch (option) {
|
||||
case MetadataOptionNames.fileName:
|
||||
case MetadataOptionNames.baselineFile:
|
||||
case MetadataOptionNames.emitThisFile:
|
||||
break;
|
||||
default:
|
||||
return option;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
@@ -4270,8 +4280,12 @@ namespace FourSlashInterface {
|
||||
this.state.baselineCurrentFileNameOrDottedNameSpans();
|
||||
}
|
||||
|
||||
public baselineGetEmitOutput(insertResultsIntoVfs?: boolean) {
|
||||
this.state.baselineGetEmitOutput(insertResultsIntoVfs);
|
||||
public getEmitOutput(expectedOutputFiles: ReadonlyArray<string>): void {
|
||||
this.state.verifyGetEmitOutput(expectedOutputFiles);
|
||||
}
|
||||
|
||||
public baselineGetEmitOutput() {
|
||||
this.state.baselineGetEmitOutput();
|
||||
}
|
||||
|
||||
public baselineQuickInfo() {
|
||||
|
||||
@@ -560,6 +560,9 @@ namespace Harness.LanguageService {
|
||||
getSourceFile(): ts.SourceFile {
|
||||
throw new Error("SourceFile can not be marshaled across the shim layer.");
|
||||
}
|
||||
getSourceMapper(): never {
|
||||
return ts.notImplemented();
|
||||
}
|
||||
dispose(): void { this.shim.dispose({}); }
|
||||
}
|
||||
|
||||
@@ -707,7 +710,9 @@ namespace Harness.LanguageService {
|
||||
return ts.sys.getEnvironmentVariable(name);
|
||||
}
|
||||
|
||||
readDirectory() { return ts.notImplemented(); }
|
||||
readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[] {
|
||||
return this.host.readDirectory(path, extensions, exclude, include, depth);
|
||||
}
|
||||
|
||||
watchFile(): ts.FileWatcher {
|
||||
return { close: ts.noop };
|
||||
|
||||
@@ -78,7 +78,9 @@ interface Array<T> {}`
|
||||
}
|
||||
|
||||
export interface SymLink {
|
||||
/** Location of the symlink. */
|
||||
path: string;
|
||||
/** Relative path to the real file. */
|
||||
symLink: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -1171,7 +1171,7 @@ namespace ts.server {
|
||||
*/
|
||||
private stopWatchingConfigFilesForClosedScriptInfo(info: ScriptInfo) {
|
||||
Debug.assert(!info.isScriptOpen());
|
||||
this.forEachConfigFileLocation(info, (configFileName, canonicalConfigFilePath) => {
|
||||
this.forEachConfigFileLocation(info, /*infoShouldBeOpen*/ true, (configFileName, canonicalConfigFilePath) => {
|
||||
const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
|
||||
if (configFileExistenceInfo) {
|
||||
const infoIsRootOfInferredProject = configFileExistenceInfo.openFilesImpactedByConfigFile.get(info.path);
|
||||
@@ -1205,7 +1205,7 @@ namespace ts.server {
|
||||
/* @internal */
|
||||
startWatchingConfigFilesForInferredProjectRoot(info: ScriptInfo) {
|
||||
Debug.assert(info.isScriptOpen());
|
||||
this.forEachConfigFileLocation(info, (configFileName, canonicalConfigFilePath) => {
|
||||
this.forEachConfigFileLocation(info, /*infoShouldBeOpen*/ true, (configFileName, canonicalConfigFilePath) => {
|
||||
let configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
|
||||
if (!configFileExistenceInfo) {
|
||||
// Create the cache
|
||||
@@ -1233,7 +1233,7 @@ namespace ts.server {
|
||||
*/
|
||||
/* @internal */
|
||||
stopWatchingConfigFilesForInferredProjectRoot(info: ScriptInfo) {
|
||||
this.forEachConfigFileLocation(info, (configFileName, canonicalConfigFilePath) => {
|
||||
this.forEachConfigFileLocation(info, /*infoShouldBeOpen*/ true, (configFileName, canonicalConfigFilePath) => {
|
||||
const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
|
||||
if (configFileExistenceInfo && configFileExistenceInfo.openFilesImpactedByConfigFile.has(info.path)) {
|
||||
Debug.assert(info.isScriptOpen());
|
||||
@@ -1256,18 +1256,18 @@ namespace ts.server {
|
||||
* The server must start searching from the directory containing
|
||||
* the newly opened file.
|
||||
*/
|
||||
private forEachConfigFileLocation(info: ScriptInfo, action: (configFileName: NormalizedPath, canonicalConfigFilePath: string) => boolean | void) {
|
||||
private forEachConfigFileLocation(info: ScriptInfo, infoShouldBeOpen: boolean, action: (configFileName: NormalizedPath, canonicalConfigFilePath: string) => boolean | void) {
|
||||
if (this.syntaxOnly) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Debug.assert(this.openFiles.has(info.path));
|
||||
Debug.assert(!infoShouldBeOpen || this.openFiles.has(info.path));
|
||||
const projectRootPath = this.openFiles.get(info.path);
|
||||
|
||||
let searchPath = asNormalizedPath(getDirectoryPath(info.fileName));
|
||||
const isSearchPathInProjectRoot = () => containsPath(projectRootPath!, searchPath, this.currentDirectory, !this.host.useCaseSensitiveFileNames);
|
||||
|
||||
// If projectRootPath doesnt contain info.path, then do normal search for config file
|
||||
// If projectRootPath doesn't contain info.path, then do normal search for config file
|
||||
const anySearchPathOk = !projectRootPath || !isSearchPathInProjectRoot();
|
||||
do {
|
||||
const canonicalSearchPath = normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName);
|
||||
@@ -1301,13 +1301,11 @@ namespace ts.server {
|
||||
* The server must start searching from the directory containing
|
||||
* the newly opened file.
|
||||
*/
|
||||
private getConfigFileNameForFile(info: ScriptInfo) {
|
||||
Debug.assert(info.isScriptOpen());
|
||||
private getConfigFileNameForFile(info: ScriptInfo, infoShouldBeOpen: boolean) {
|
||||
if (infoShouldBeOpen) Debug.assert(info.isScriptOpen());
|
||||
this.logger.info(`Search path: ${getDirectoryPath(info.fileName)}`);
|
||||
const configFileName = this.forEachConfigFileLocation(info,
|
||||
(configFileName, canonicalConfigFilePath) =>
|
||||
this.configFileExists(configFileName, canonicalConfigFilePath, info)
|
||||
);
|
||||
const configFileName = this.forEachConfigFileLocation(info, infoShouldBeOpen, (configFileName, canonicalConfigFilePath) =>
|
||||
this.configFileExists(configFileName, canonicalConfigFilePath, info));
|
||||
if (configFileName) {
|
||||
this.logger.info(`For info: ${info.fileName} :: Config file name: ${configFileName}`);
|
||||
}
|
||||
@@ -1840,13 +1838,11 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined, hostToQueryFileExistsOn: DirectoryStructureHost | undefined) {
|
||||
private getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined, hostToQueryFileExistsOn: DirectoryStructureHost | undefined) {
|
||||
return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, fileContent: string | undefined, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined) {
|
||||
private getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, fileContent: string | undefined, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined) {
|
||||
return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent);
|
||||
}
|
||||
|
||||
@@ -1989,7 +1985,7 @@ namespace ts.server {
|
||||
// we first detect if there is already a configured project created for it: if so,
|
||||
// we re- read the tsconfig file content and update the project only if we havent already done so
|
||||
// otherwise we create a new one.
|
||||
const configFileName = this.getConfigFileNameForFile(info);
|
||||
const configFileName = this.getConfigFileNameForFile(info, /*infoShouldBeOpen*/ true);
|
||||
if (configFileName) {
|
||||
const project = this.findConfiguredProjectByProjectName(configFileName);
|
||||
if (!project) {
|
||||
@@ -2077,6 +2073,24 @@ namespace ts.server {
|
||||
return this.openClientFileWithNormalizedPath(toNormalizedPath(fileName), fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath ? toNormalizedPath(projectRootPath) : undefined);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
getProjectForFileWithoutOpening(fileName: NormalizedPath): { readonly scriptInfo: ScriptInfo, readonly projects: ReadonlyArray<Project> } | undefined {
|
||||
const scriptInfo = this.filenameToScriptInfo.get(fileName) ||
|
||||
this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName, this.currentDirectory, /*fileContent*/ undefined, /*scriptKind*/ undefined, /*hasMixedContent*/ undefined);
|
||||
if (!scriptInfo) return undefined;
|
||||
if (scriptInfo.containingProjects.length) {
|
||||
return { scriptInfo, projects: scriptInfo.containingProjects };
|
||||
}
|
||||
const configFileName = this.getConfigFileNameForFile(scriptInfo, /*infoShouldBeOpen*/ false);
|
||||
const project = configFileName === undefined ? undefined : this.findConfiguredProjectByProjectName(configFileName) || this.createConfiguredProject(configFileName);
|
||||
return project && project.containsScriptInfo(scriptInfo) ? { scriptInfo, projects: [project] } : undefined;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
fileExists(fileName: NormalizedPath): boolean {
|
||||
return this.filenameToScriptInfo.has(fileName) || this.host.fileExists(fileName);
|
||||
}
|
||||
|
||||
private findExternalProjectContainingOpenScriptInfo(info: ScriptInfo): ExternalProject | undefined {
|
||||
return find(this.externalProjects, proj => {
|
||||
// Ensure project structure is up-to-date to check if info is present in external project
|
||||
@@ -2090,10 +2104,11 @@ namespace ts.server {
|
||||
let configFileErrors: ReadonlyArray<Diagnostic> | undefined;
|
||||
|
||||
const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent)!; // TODO: GH#18217
|
||||
|
||||
this.openFiles.set(info.path, projectRootPath);
|
||||
let project: ConfiguredProject | ExternalProject | undefined = this.findExternalProjectContainingOpenScriptInfo(info);
|
||||
if (!project && !this.syntaxOnly) { // Checking syntaxOnly is an optimization
|
||||
configFileName = this.getConfigFileNameForFile(info);
|
||||
configFileName = this.getConfigFileNameForFile(info, /*infoShouldBeOpen*/ true);
|
||||
if (configFileName) {
|
||||
project = this.findConfiguredProjectByProjectName(configFileName);
|
||||
if (!project) {
|
||||
|
||||
@@ -271,8 +271,8 @@ namespace ts.server {
|
||||
return this.projectStateVersion.toString();
|
||||
}
|
||||
|
||||
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined {
|
||||
return undefined;
|
||||
getProjectReferences(): ReadonlyArray<ProjectReference> {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
getScriptFileNames() {
|
||||
@@ -461,6 +461,11 @@ namespace ts.server {
|
||||
return this.languageService;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
getSourceMapper(): SourceMapper {
|
||||
return this.getLanguageService().getSourceMapper();
|
||||
}
|
||||
|
||||
private shouldEmitFile(scriptInfo: ScriptInfo) {
|
||||
return scriptInfo && !scriptInfo.isDynamicOrHasMixedContent();
|
||||
}
|
||||
@@ -1351,8 +1356,8 @@ namespace ts.server {
|
||||
return asNormalizedPath(this.getProjectName());
|
||||
}
|
||||
|
||||
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined {
|
||||
return this.projectReferences;
|
||||
getProjectReferences(): ReadonlyArray<ProjectReference> {
|
||||
return this.projectReferences || emptyArray;
|
||||
}
|
||||
|
||||
updateReferences(refs: ReadonlyArray<ProjectReference> | undefined) {
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace ts.server.protocol {
|
||||
Implementation = "implementation",
|
||||
/* @internal */
|
||||
ImplementationFull = "implementation-full",
|
||||
/* @internal */
|
||||
EmitOutput = "emit-output",
|
||||
Exit = "exit",
|
||||
Format = "format",
|
||||
Formatonkey = "formatonkey",
|
||||
@@ -794,6 +796,21 @@ namespace ts.server.protocol {
|
||||
command: CommandTypes.Definition;
|
||||
}
|
||||
|
||||
export interface DefinitionAndBoundSpanRequest extends FileLocationRequest {
|
||||
readonly command: CommandTypes.DefinitionAndBoundSpan;
|
||||
}
|
||||
|
||||
export interface DefinitionAndBoundSpanResponse extends Response {
|
||||
readonly body: DefinitionInfoAndBoundSpan;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface EmitOutputRequest extends FileRequest {}
|
||||
/** @internal */
|
||||
export interface EmitOutputResponse extends Response {
|
||||
readonly body: EmitOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go to type request; value of command field is
|
||||
* "typeDefinition". Return response giving the file locations that
|
||||
@@ -1056,6 +1073,17 @@ namespace ts.server.protocol {
|
||||
arguments: RenameRequestArgs;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface RenameFullRequest extends FileLocationRequest {
|
||||
readonly command: CommandTypes.RenameLocationsFull;
|
||||
readonly arguments: RenameRequestArgs;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface RenameFullResponse extends Response {
|
||||
readonly body: ReadonlyArray<RenameLocation>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about the item to be renamed.
|
||||
*/
|
||||
|
||||
+287
-273
@@ -42,31 +42,6 @@ namespace ts.server {
|
||||
return false;
|
||||
}
|
||||
|
||||
interface FileStart {
|
||||
file: string;
|
||||
start: protocol.Location;
|
||||
}
|
||||
|
||||
function compareNumber(a: number, b: number) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
function compareFileStart(a: FileStart, b: FileStart) {
|
||||
if (a.file < b.file) {
|
||||
return -1;
|
||||
}
|
||||
else if (a.file === b.file) {
|
||||
const n = compareNumber(a.start.line, b.start.line);
|
||||
if (n === 0) {
|
||||
return compareNumber(a.start.offset, b.start.offset);
|
||||
}
|
||||
else return n;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
function formatDiag(fileName: NormalizedPath, project: Project, diag: Diagnostic): protocol.Diagnostic {
|
||||
const scriptInfo = project.getScriptInfoForNormalizedPath(fileName)!; // TODO: GH#18217
|
||||
return {
|
||||
@@ -279,8 +254,8 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
type Projects = ReadonlyArray<Project> | {
|
||||
projects: ReadonlyArray<Project>;
|
||||
symLinkedProjects: MultiMap<Project>;
|
||||
readonly projects: ReadonlyArray<Project>;
|
||||
readonly symLinkedProjects: MultiMap<Project>;
|
||||
};
|
||||
|
||||
function isProjectsArray(projects: Projects): projects is ReadonlyArray<Project> {
|
||||
@@ -290,7 +265,14 @@ namespace ts.server {
|
||||
/**
|
||||
* This helper function processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project.
|
||||
*/
|
||||
function combineProjectOutput<T, U>(defaultValue: T, getValue: (path: Path) => T, projects: Projects, action: (project: Project, value: T) => ReadonlyArray<U> | U | undefined, comparer?: (a: U, b: U) => number, areEqual?: (a: U, b: U) => boolean) {
|
||||
function combineProjectOutput<T, U>(
|
||||
defaultValue: T,
|
||||
getValue: (path: Path) => T,
|
||||
projects: Projects,
|
||||
action: (project: Project, value: T) => ReadonlyArray<U> | U | undefined,
|
||||
comparer?: (a: U, b: U) => number,
|
||||
areEqual?: (a: U, b: U) => boolean,
|
||||
): U[] {
|
||||
const outputs = flatMap(isProjectsArray(projects) ? projects : projects.projects, project => action(project, defaultValue));
|
||||
if (!isProjectsArray(projects) && projects.symLinkedProjects) {
|
||||
projects.symLinkedProjects.forEach((projects, path) => {
|
||||
@@ -304,6 +286,150 @@ namespace ts.server {
|
||||
: deduplicate(outputs, areEqual);
|
||||
}
|
||||
|
||||
function combineProjectOutputWhileOpeningReferencedProjects<T>(
|
||||
projects: Projects,
|
||||
projectService: ProjectService,
|
||||
action: (project: Project) => ReadonlyArray<T>,
|
||||
getLocation: (t: T) => sourcemaps.SourceMappableLocation,
|
||||
resultsEqual: (a: T, b: T) => boolean,
|
||||
): T[] {
|
||||
const outputs: T[] = [];
|
||||
combineProjectOutputWorker(projects, <sourcemaps.SourceMappableLocation><any>undefined, projectService, ({ project }, tryAddToTodo) => {
|
||||
for (const output of action(project)) {
|
||||
if (!contains(outputs, output, resultsEqual) && !tryAddToTodo(project, getLocation(output))) {
|
||||
outputs.push(output);
|
||||
}
|
||||
}
|
||||
});
|
||||
return outputs;
|
||||
}
|
||||
|
||||
function combineProjectOutputForRenameLocations(projects: Projects, initialLocation: sourcemaps.SourceMappableLocation, projectService: ProjectService, findInStrings: boolean, findInComments: boolean): ReadonlyArray<RenameLocation> {
|
||||
const outputs: RenameLocation[] = [];
|
||||
|
||||
combineProjectOutputWorker(projects, initialLocation, projectService, ({ project, location }, tryAddToTodo) => {
|
||||
for (const output of project.getLanguageService().findRenameLocations(location.fileName, location.position, findInStrings, findInComments) || emptyArray) {
|
||||
if (!contains(outputs, output, documentSpansEqual) && !tryAddToTodo(project, documentSpanLocation(output))) {
|
||||
outputs.push(output);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return outputs;
|
||||
}
|
||||
|
||||
function combineProjectOutputForReferences(projects: Projects, initialLocation: sourcemaps.SourceMappableLocation, projectService: ProjectService): ReadonlyArray<ReferencedSymbol> {
|
||||
const outputs: ReferencedSymbol[] = [];
|
||||
|
||||
combineProjectOutputWorker(projects, initialLocation, projectService, ({ project, location }, tryAddToTodo) => {
|
||||
for (const outputReferencedSymbol of project.getLanguageService().findReferences(location.fileName, location.position) || emptyArray) {
|
||||
let symbolToAddTo = find(outputs, o => documentSpansEqual(o.definition, outputReferencedSymbol.definition));
|
||||
if (!symbolToAddTo) {
|
||||
symbolToAddTo = { definition: outputReferencedSymbol.definition, references: [] };
|
||||
outputs.push(symbolToAddTo);
|
||||
}
|
||||
|
||||
for (const ref of outputReferencedSymbol.references) {
|
||||
if (!contains(symbolToAddTo.references, ref, documentSpansEqual) && !tryAddToTodo(project, documentSpanLocation(ref))) {
|
||||
symbolToAddTo.references.push(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return outputs.filter(o => o.references.length !== 0);
|
||||
}
|
||||
|
||||
interface ProjectAndLocation {
|
||||
readonly project: Project;
|
||||
readonly location: sourcemaps.SourceMappableLocation;
|
||||
}
|
||||
|
||||
interface ToDoAndSeenProjects {
|
||||
readonly toDo: ProjectAndLocation[];
|
||||
readonly seenProjects: Map<true>;
|
||||
}
|
||||
|
||||
function combineProjectOutputWorker(
|
||||
projects: Projects,
|
||||
initialLocation: sourcemaps.SourceMappableLocation,
|
||||
projectService: ProjectService,
|
||||
cb: (where: ProjectAndLocation, getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => boolean) => void,
|
||||
): void {
|
||||
let toDoAndSeenProjects: ToDoAndSeenProjects | undefined;
|
||||
for (const project of isProjectsArray(projects) ? projects : projects.projects) {
|
||||
toDoAndSeenProjects = callbackProjectAndLocation(projects, { project, location: initialLocation }, projectService, toDoAndSeenProjects, cb);
|
||||
}
|
||||
if (!isArray(projects) && projects.symLinkedProjects) {
|
||||
projects.symLinkedProjects.forEach((symlinkedProjects, path) => {
|
||||
for (const project of symlinkedProjects) {
|
||||
toDoAndSeenProjects = callbackProjectAndLocation(projects, { project, location: { fileName: path, position: initialLocation.position } }, projectService, toDoAndSeenProjects, cb);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
while (toDoAndSeenProjects && toDoAndSeenProjects.toDo.length) {
|
||||
toDoAndSeenProjects = callbackProjectAndLocation(projects, Debug.assertDefined(toDoAndSeenProjects.toDo.pop()), projectService, toDoAndSeenProjects, cb);
|
||||
}
|
||||
}
|
||||
|
||||
function callbackProjectAndLocation(
|
||||
originalProjects: Projects, // For lazily populating seenProjects
|
||||
projectAndLocation: ProjectAndLocation,
|
||||
projectService: ProjectService,
|
||||
toDoAndSeenProjects: ToDoAndSeenProjects | undefined,
|
||||
cb: (where: ProjectAndLocation, getMappedLocation: (project: Project, location: sourcemaps.SourceMappableLocation) => boolean) => void,
|
||||
): ToDoAndSeenProjects | undefined {
|
||||
if (projectAndLocation.project.getCancellationToken().isCancellationRequested()) return undefined; // Skip rest of toDo if cancelled
|
||||
cb(projectAndLocation, (project, location) => {
|
||||
const originalLocation = project.getSourceMapper().tryGetOriginalLocation(location);
|
||||
if (!originalLocation) return false;
|
||||
const originalProjectAndScriptInfo = projectService.getProjectForFileWithoutOpening(toNormalizedPath(originalLocation.fileName));
|
||||
if (!originalProjectAndScriptInfo) return false;
|
||||
|
||||
if (originalProjectAndScriptInfo) {
|
||||
if (toDoAndSeenProjects === undefined) {
|
||||
toDoAndSeenProjects = { toDo: [], seenProjects: createMap<true>() };
|
||||
for (const project of isProjectsArray(originalProjects) ? originalProjects : originalProjects.projects) {
|
||||
toDoAndSeenProjects.seenProjects.set(project.projectName, true);
|
||||
}
|
||||
if (!isArray(originalProjects) && originalProjects.symLinkedProjects) {
|
||||
originalProjects.symLinkedProjects.forEach(symlinkedProjects => {
|
||||
for (const project of symlinkedProjects) {
|
||||
toDoAndSeenProjects!.seenProjects.set(project.projectName, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (const project of originalProjectAndScriptInfo.projects) {
|
||||
addToTodo({ project, location: originalLocation }, toDoAndSeenProjects);
|
||||
}
|
||||
const symlinkedProjectsMap = projectService.getSymlinkedProjects(originalProjectAndScriptInfo.scriptInfo);
|
||||
if (symlinkedProjectsMap) {
|
||||
symlinkedProjectsMap.forEach((symlinkedProjects) => {
|
||||
for (const symlinkedProject of symlinkedProjects) addToTodo({ project: symlinkedProject, location: originalLocation }, toDoAndSeenProjects!);
|
||||
});
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return toDoAndSeenProjects;
|
||||
}
|
||||
|
||||
function addToTodo(projectAndLocation: ProjectAndLocation, { seenProjects, toDo }: ToDoAndSeenProjects): void {
|
||||
if (addToSeen(seenProjects, projectAndLocation.project.projectName)) toDo.push(projectAndLocation);
|
||||
}
|
||||
|
||||
function documentSpanLocation({ fileName, textSpan }: DocumentSpan): sourcemaps.SourceMappableLocation {
|
||||
return { fileName, position: textSpan.start };
|
||||
}
|
||||
|
||||
function getMappedLocation(location: sourcemaps.SourceMappableLocation, projectService: ProjectService, project: Project): sourcemaps.SourceMappableLocation | undefined {
|
||||
const mapsTo = project.getSourceMapper().tryGetOriginalLocation(location);
|
||||
return mapsTo && projectService.fileExists(toNormalizedPath(mapsTo.fileName)) ? mapsTo : undefined;
|
||||
}
|
||||
|
||||
export interface SessionOptions {
|
||||
host: ServerHost;
|
||||
cancellationToken: ServerCancellationToken;
|
||||
@@ -690,46 +816,64 @@ namespace ts.server {
|
||||
private getDefinition(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.FileSpan> | 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);
|
||||
return simplifiedResult ? this.mapDefinitionInfo(definitions, project) : definitions.map(Session.mapToOriginalLocation);
|
||||
}
|
||||
|
||||
const definitions = project.getLanguageService().getDefinitionAtPosition(file, position);
|
||||
if (!definitions) {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
if (simplifiedResult) {
|
||||
return this.mapDefinitionInfo(definitions, project);
|
||||
}
|
||||
|
||||
return definitions.map(Session.mapToOriginalLocation);
|
||||
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 : {
|
||||
containerKind: info.containerKind,
|
||||
containerName: info.containerName,
|
||||
fileName: newLoc.fileName,
|
||||
kind: info.kind,
|
||||
name: info.name,
|
||||
textSpan: {
|
||||
start: newLoc.position,
|
||||
length: info.textSpan.length
|
||||
},
|
||||
originalFileName: info.fileName,
|
||||
originalTextSpan: info.textSpan,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private getDefinitionAndBoundSpan(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.DefinitionInfoAndBoundSpan | DefinitionInfoAndBoundSpan {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
const scriptInfo = project.getScriptInfo(file)!;
|
||||
const scriptInfo = Debug.assertDefined(project.getScriptInfo(file));
|
||||
|
||||
const definitionAndBoundSpan = project.getLanguageService().getDefinitionAndBoundSpan(file, position);
|
||||
const unmappedDefinitionAndBoundSpan = project.getLanguageService().getDefinitionAndBoundSpan(file, position);
|
||||
|
||||
if (!definitionAndBoundSpan || !definitionAndBoundSpan.definitions) {
|
||||
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(definitionAndBoundSpan.definitions, project),
|
||||
textSpan: this.toLocationTextSpan(definitionAndBoundSpan.textSpan, scriptInfo)
|
||||
definitions: this.mapDefinitionInfo(definitions, project),
|
||||
textSpan: this.toLocationTextSpan(textSpan, scriptInfo)
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...definitionAndBoundSpan,
|
||||
definitions: definitionAndBoundSpan.definitions.map(Session.mapToOriginalLocation)
|
||||
definitions: definitions.map(Session.mapToOriginalLocation),
|
||||
textSpan,
|
||||
};
|
||||
}
|
||||
|
||||
private getEmitOutput(args: protocol.FileRequestArgs): EmitOutput {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
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));
|
||||
}
|
||||
@@ -771,21 +915,31 @@ namespace ts.server {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
|
||||
const definitions = project.getLanguageService().getTypeDefinitionAtPosition(file, position);
|
||||
if (!definitions) {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
const definitions = this.mapDefinitionInfoLocations(project.getLanguageService().getTypeDefinitionAtPosition(file, position) || emptyArray, project);
|
||||
return this.mapDefinitionInfo(definitions, project);
|
||||
}
|
||||
|
||||
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,
|
||||
kind: info.kind,
|
||||
displayParts: info.displayParts,
|
||||
textSpan: {
|
||||
start: newLoc.position,
|
||||
length: info.textSpan.length
|
||||
},
|
||||
originalFileName: info.fileName,
|
||||
originalTextSpan: info.textSpan,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private getImplementation(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.FileSpan> | ReadonlyArray<ImplementationLocation> {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
const implementations = project.getLanguageService().getImplementationAtPosition(file, position);
|
||||
if (!implementations) {
|
||||
return emptyArray;
|
||||
}
|
||||
const implementations = this.mapImplementationLocations(project.getLanguageService().getImplementationAtPosition(file, position) || emptyArray, project);
|
||||
if (simplifiedResult) {
|
||||
return implementations.map(({ fileName, textSpan }) => this.toFileSpan(fileName, textSpan, project));
|
||||
}
|
||||
@@ -948,179 +1102,59 @@ namespace ts.server {
|
||||
return info.getDefaultProject();
|
||||
}
|
||||
|
||||
private getRenameLocations(args: protocol.RenameRequestArgs, simplifiedResult: boolean): protocol.RenameResponseBody | ReadonlyArray<RenameLocation> | undefined {
|
||||
private getRenameLocations(args: protocol.RenameRequestArgs, simplifiedResult: boolean): protocol.RenameResponseBody | ReadonlyArray<RenameLocation> {
|
||||
const file = toNormalizedPath(args.file);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
const projects = this.getProjects(args);
|
||||
if (simplifiedResult) {
|
||||
|
||||
const defaultProject = this.getDefaultProject(args);
|
||||
// The rename info should be the same for every project
|
||||
const renameInfo = defaultProject.getLanguageService().getRenameInfo(file, position);
|
||||
if (!renameInfo) {
|
||||
return undefined;
|
||||
}
|
||||
const locations = combineProjectOutputForRenameLocations(projects, { fileName: args.file, position }, this.projectService, !!args.findInStrings, !!args.findInComments);
|
||||
if (!simplifiedResult) return locations;
|
||||
|
||||
if (!renameInfo.canRename) {
|
||||
return {
|
||||
info: renameInfo,
|
||||
locs: emptyArray
|
||||
};
|
||||
}
|
||||
const defaultProject = this.getDefaultProject(args);
|
||||
const renameInfo = Session.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position));
|
||||
return { info: renameInfo, locs: this.toSpanGroups(locations) };
|
||||
}
|
||||
|
||||
const fileSpans = combineProjectOutput(
|
||||
file,
|
||||
path => this.projectService.getScriptInfoForPath(path)!.fileName,
|
||||
projects,
|
||||
(project, file) => {
|
||||
const renameLocations = project.getLanguageService().findRenameLocations(file, position, args.findInStrings!, args.findInComments!);
|
||||
if (!renameLocations) {
|
||||
return emptyArray;
|
||||
}
|
||||
// strips 'triggerSpan'
|
||||
private static mapRenameInfo({ canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers }: RenameInfo): protocol.RenameInfo {
|
||||
return { canRename, localizedErrorMessage, displayName, fullDisplayName, kind, kindModifiers };
|
||||
}
|
||||
|
||||
return renameLocations.map(location => {
|
||||
const locationScriptInfo = project.getScriptInfo(location.fileName)!;
|
||||
return {
|
||||
file: location.fileName,
|
||||
start: locationScriptInfo.positionToLineOffset(location.textSpan.start),
|
||||
end: locationScriptInfo.positionToLineOffset(textSpanEnd(location.textSpan)),
|
||||
};
|
||||
});
|
||||
},
|
||||
compareRenameLocation,
|
||||
(a, b) => a.file === b.file && a.start.line === b.start.line && a.start.offset === b.start.offset
|
||||
);
|
||||
|
||||
const locs: protocol.SpanGroup[] = [];
|
||||
for (const cur of fileSpans) {
|
||||
let curFileAccum: protocol.SpanGroup | undefined;
|
||||
if (locs.length > 0) {
|
||||
curFileAccum = locs[locs.length - 1];
|
||||
if (curFileAccum.file !== cur.file) {
|
||||
curFileAccum = undefined;
|
||||
}
|
||||
}
|
||||
if (!curFileAccum) {
|
||||
curFileAccum = { file: cur.file, locs: [] };
|
||||
locs.push(curFileAccum);
|
||||
}
|
||||
curFileAccum.locs.push({ start: cur.start, end: cur.end });
|
||||
}
|
||||
|
||||
return { info: renameInfo, locs };
|
||||
}
|
||||
else {
|
||||
return combineProjectOutput(
|
||||
file,
|
||||
path => this.projectService.getScriptInfoForPath(path)!.fileName,
|
||||
projects,
|
||||
(p, file) => p.getLanguageService().findRenameLocations(file, position, args.findInStrings!, args.findInComments!),
|
||||
/*comparer*/ undefined,
|
||||
renameLocationIsEqualTo
|
||||
);
|
||||
}
|
||||
|
||||
function renameLocationIsEqualTo(a: RenameLocation, b: RenameLocation) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return a.fileName === b.fileName &&
|
||||
a.textSpan.start === b.textSpan.start &&
|
||||
a.textSpan.length === b.textSpan.length;
|
||||
}
|
||||
|
||||
function compareRenameLocation(a: protocol.FileSpan, b: protocol.FileSpan) {
|
||||
if (a.file < b.file) {
|
||||
return -1;
|
||||
}
|
||||
else if (a.file > b.file) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
// reverse sort assuming no overlap
|
||||
if (a.start.line < b.start.line) {
|
||||
return 1;
|
||||
}
|
||||
else if (a.start.line > b.start.line) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return b.start.offset - a.start.offset;
|
||||
}
|
||||
}
|
||||
private toSpanGroups(locations: ReadonlyArray<RenameLocation>): ReadonlyArray<protocol.SpanGroup> {
|
||||
const map = createMap<protocol.SpanGroup>();
|
||||
for (const { fileName, textSpan } of locations) {
|
||||
let group = map.get(fileName);
|
||||
if (!group) map.set(fileName, group = { file: fileName, locs: [] });
|
||||
group.locs.push(this.toLocationTextSpan(textSpan, Debug.assertDefined(this.projectService.getScriptInfo(fileName))));
|
||||
}
|
||||
return arrayFrom(map.values());
|
||||
}
|
||||
|
||||
private getReferences(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.ReferencesResponseBody | undefined | ReadonlyArray<ReferencedSymbol> {
|
||||
const file = toNormalizedPath(args.file);
|
||||
const projects = this.getProjects(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
const references = combineProjectOutputForReferences(projects, { fileName: args.file, position }, this.projectService);
|
||||
|
||||
const defaultProject = this.getDefaultProject(args);
|
||||
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
|
||||
const position = this.getPosition(args, scriptInfo);
|
||||
if (simplifiedResult) {
|
||||
const defaultProject = this.getDefaultProject(args);
|
||||
const scriptInfo = defaultProject.getScriptInfoForNormalizedPath(file)!;
|
||||
const nameInfo = defaultProject.getLanguageService().getQuickInfoAtPosition(file, position);
|
||||
const displayString = nameInfo ? displayPartsToString(nameInfo.displayParts) : "";
|
||||
const symbolDisplayString = nameInfo ? displayPartsToString(nameInfo.displayParts) : "";
|
||||
const nameSpan = nameInfo && nameInfo.textSpan;
|
||||
const nameColStart = nameSpan ? scriptInfo.positionToLineOffset(nameSpan.start).offset : 0;
|
||||
const nameText = nameSpan ? scriptInfo.getSnapshot().getText(nameSpan.start, textSpanEnd(nameSpan)) : "";
|
||||
const refs = combineProjectOutput<NormalizedPath, protocol.ReferencesResponseItem>(
|
||||
file,
|
||||
path => this.projectService.getScriptInfoForPath(path)!.fileName,
|
||||
projects,
|
||||
(project, file) => {
|
||||
const references = project.getLanguageService().getReferencesAtPosition(file, position);
|
||||
if (!references) {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
return references.map(ref => {
|
||||
const refScriptInfo = project.getScriptInfo(ref.fileName)!;
|
||||
const start = refScriptInfo.positionToLineOffset(ref.textSpan.start);
|
||||
const refLineSpan = refScriptInfo.lineToTextSpan(start.line - 1);
|
||||
const lineText = refScriptInfo.getSnapshot().getText(refLineSpan.start, textSpanEnd(refLineSpan)).replace(/\r|\n/g, "");
|
||||
return {
|
||||
file: ref.fileName,
|
||||
start,
|
||||
lineText,
|
||||
end: refScriptInfo.positionToLineOffset(textSpanEnd(ref.textSpan)),
|
||||
isWriteAccess: ref.isWriteAccess,
|
||||
isDefinition: ref.isDefinition
|
||||
};
|
||||
});
|
||||
},
|
||||
compareFileStart,
|
||||
areReferencesResponseItemsForTheSameLocation
|
||||
);
|
||||
|
||||
return {
|
||||
refs,
|
||||
symbolName: nameText,
|
||||
symbolStartOffset: nameColStart,
|
||||
symbolDisplayString: displayString
|
||||
};
|
||||
const symbolStartOffset = nameSpan ? scriptInfo.positionToLineOffset(nameSpan.start).offset : 0;
|
||||
const symbolName = nameSpan ? scriptInfo.getSnapshot().getText(nameSpan.start, textSpanEnd(nameSpan)) : "";
|
||||
const refs: protocol.ReferencesResponseItem[] = flatMap(references, referencedSymbol =>
|
||||
referencedSymbol.references.map(({ fileName, textSpan, isWriteAccess, isDefinition }): protocol.ReferencesResponseItem => {
|
||||
const scriptInfo = Debug.assertDefined(this.projectService.getScriptInfo(fileName));
|
||||
const lineText = scriptInfo.getSnapshot().getText(textSpan.start, textSpanEnd(textSpan));
|
||||
return { ...toFileSpan(fileName, textSpan, scriptInfo), lineText, isWriteAccess, isDefinition };
|
||||
}));
|
||||
const result: protocol.ReferencesResponseBody = { refs, symbolName, symbolStartOffset, symbolDisplayString };
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return combineProjectOutput(
|
||||
file,
|
||||
path => this.projectService.getScriptInfoForPath(path)!.fileName,
|
||||
projects,
|
||||
(project, file) => project.getLanguageService().findReferences(file, position),
|
||||
/*comparer*/ undefined,
|
||||
equateValues
|
||||
);
|
||||
}
|
||||
|
||||
function areReferencesResponseItemsForTheSameLocation(a: protocol.ReferencesResponseItem, b: protocol.ReferencesResponseItem) {
|
||||
if (a && b) {
|
||||
return a.file === b.file &&
|
||||
a.start === b.start &&
|
||||
a.end === b.end;
|
||||
}
|
||||
return false;
|
||||
return references;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1568,63 +1602,45 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
private getNavigateToItems(args: protocol.NavtoRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.NavtoItem> | ReadonlyArray<NavigateToItem> {
|
||||
const projects = this.getProjects(args);
|
||||
const full = this.getFullNavigateToItems(args);
|
||||
return !simplifiedResult ? full : full.map((navItem) => {
|
||||
const { file, project } = this.getFileAndProject({ file: navItem.fileName });
|
||||
const scriptInfo = project.getScriptInfo(file)!;
|
||||
const bakedItem: protocol.NavtoItem = {
|
||||
name: navItem.name,
|
||||
kind: navItem.kind,
|
||||
isCaseSensitive: navItem.isCaseSensitive,
|
||||
matchKind: navItem.matchKind,
|
||||
file: navItem.fileName,
|
||||
start: scriptInfo.positionToLineOffset(navItem.textSpan.start),
|
||||
end: scriptInfo.positionToLineOffset(textSpanEnd(navItem.textSpan))
|
||||
};
|
||||
if (navItem.kindModifiers && (navItem.kindModifiers !== "")) {
|
||||
bakedItem.kindModifiers = navItem.kindModifiers;
|
||||
}
|
||||
if (navItem.containerName && (navItem.containerName.length > 0)) {
|
||||
bakedItem.containerName = navItem.containerName;
|
||||
}
|
||||
if (navItem.containerKind && (navItem.containerKind.length > 0)) {
|
||||
bakedItem.containerKind = navItem.containerKind;
|
||||
}
|
||||
return bakedItem;
|
||||
});
|
||||
}
|
||||
|
||||
const fileName = args.currentFileOnly ? args.file && normalizeSlashes(args.file) : undefined;
|
||||
if (simplifiedResult) {
|
||||
return combineProjectOutput(
|
||||
fileName,
|
||||
() => undefined,
|
||||
projects,
|
||||
(project, file) => {
|
||||
if (fileName && !file) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const navItems = project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, fileName, /*excludeDts*/ project.isNonTsProject());
|
||||
if (!navItems) {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
return navItems.map((navItem) => {
|
||||
const scriptInfo = project.getScriptInfo(navItem.fileName)!;
|
||||
const bakedItem: protocol.NavtoItem = {
|
||||
name: navItem.name,
|
||||
kind: navItem.kind,
|
||||
isCaseSensitive: navItem.isCaseSensitive,
|
||||
matchKind: navItem.matchKind,
|
||||
file: navItem.fileName,
|
||||
start: scriptInfo.positionToLineOffset(navItem.textSpan.start),
|
||||
end: scriptInfo.positionToLineOffset(textSpanEnd(navItem.textSpan))
|
||||
};
|
||||
if (navItem.kindModifiers && (navItem.kindModifiers !== "")) {
|
||||
bakedItem.kindModifiers = navItem.kindModifiers;
|
||||
}
|
||||
if (navItem.containerName && (navItem.containerName.length > 0)) {
|
||||
bakedItem.containerName = navItem.containerName;
|
||||
}
|
||||
if (navItem.containerKind && (navItem.containerKind.length > 0)) {
|
||||
bakedItem.containerKind = navItem.containerKind;
|
||||
}
|
||||
return bakedItem;
|
||||
});
|
||||
},
|
||||
/*comparer*/ undefined,
|
||||
areNavToItemsForTheSameLocation
|
||||
);
|
||||
private getFullNavigateToItems(args: protocol.NavtoRequestArgs): ReadonlyArray<NavigateToItem> {
|
||||
const { currentFileOnly, searchValue, maxResultCount } = args;
|
||||
if (currentFileOnly) {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
return project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, file);
|
||||
}
|
||||
else {
|
||||
return combineProjectOutput(
|
||||
fileName,
|
||||
() => undefined,
|
||||
projects,
|
||||
(project, file) => {
|
||||
if (fileName && !file) {
|
||||
return undefined;
|
||||
}
|
||||
return project.getLanguageService().getNavigateToItems(args.searchValue, args.maxResultCount, fileName, /*excludeDts*/ project.isNonTsProject());
|
||||
},
|
||||
/*comparer*/ undefined,
|
||||
return combineProjectOutputWhileOpeningReferencedProjects<NavigateToItem>(
|
||||
this.getProjects(args),
|
||||
this.projectService,
|
||||
project =>
|
||||
project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, /*fileName*/ undefined, /*excludeDts*/ project.isNonTsProject()),
|
||||
documentSpanLocation,
|
||||
navigateToItemIsEqualTo);
|
||||
}
|
||||
|
||||
@@ -1646,15 +1662,6 @@ namespace ts.server {
|
||||
a.textSpan.start === b.textSpan.start &&
|
||||
a.textSpan.length === b.textSpan.length;
|
||||
}
|
||||
|
||||
function areNavToItemsForTheSameLocation(a: protocol.NavtoItem, b: protocol.NavtoItem) {
|
||||
if (a && b) {
|
||||
return a.file === b.file &&
|
||||
a.start === b.start &&
|
||||
a.end === b.end;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private getSupportedCodeFixes(): string[] {
|
||||
@@ -1976,6 +1983,9 @@ namespace ts.server {
|
||||
[CommandNames.DefinitionAndBoundSpanFull]: (request: protocol.DefinitionRequest) => {
|
||||
return this.requiredResponse(this.getDefinitionAndBoundSpan(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.EmitOutput]: (request: protocol.EmitOutputRequest) => {
|
||||
return this.requiredResponse(this.getEmitOutput(request.arguments));
|
||||
},
|
||||
[CommandNames.TypeDefinition]: (request: protocol.FileLocationRequest) => {
|
||||
return this.requiredResponse(this.getTypeDefinition(request.arguments));
|
||||
},
|
||||
@@ -1991,10 +2001,10 @@ namespace ts.server {
|
||||
[CommandNames.ReferencesFull]: (request: protocol.FileLocationRequest) => {
|
||||
return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.Rename]: (request: protocol.Request) => {
|
||||
[CommandNames.Rename]: (request: protocol.RenameRequest) => {
|
||||
return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.RenameLocationsFull]: (request: protocol.RenameRequest) => {
|
||||
[CommandNames.RenameLocationsFull]: (request: protocol.RenameFullRequest) => {
|
||||
return this.requiredResponse(this.getRenameLocations(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
[CommandNames.RenameInfoFull]: (request: protocol.FileLocationRequest) => {
|
||||
@@ -2332,6 +2342,10 @@ 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 mapTextChangesToCodeEdits(textChanges: FileTextChanges, sourceFile: SourceFile | undefined): protocol.FileCodeEdits {
|
||||
Debug.assert(!!textChanges.isNewFile === !sourceFile);
|
||||
if (sourceFile) {
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace ts.NavigateTo {
|
||||
for (const sourceFile of sourceFiles) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
if (excludeDtsFiles && fileExtensionIs(sourceFile.fileName, Extension.Dts)) {
|
||||
if (excludeDtsFiles && sourceFile.isDeclarationFile) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+9
-166
@@ -1129,8 +1129,6 @@ namespace ts {
|
||||
localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages();
|
||||
}
|
||||
|
||||
let sourcemappedFileCache: SourceFileLikeCache;
|
||||
|
||||
function log(message: string) {
|
||||
if (host.log) {
|
||||
host.log(message);
|
||||
@@ -1140,6 +1138,8 @@ namespace ts {
|
||||
const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames(host);
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
|
||||
const sourceMapper = getSourceMapper(getCanonicalFileName, currentDirectory, log, host, () => program);
|
||||
|
||||
function getValidSourceFile(fileName: string): SourceFile {
|
||||
const sourceFile = program.getSourceFile(fileName);
|
||||
if (!sourceFile) {
|
||||
@@ -1251,7 +1251,7 @@ namespace ts {
|
||||
// We reset this cache on structure invalidation so we don't hold on to outdated files for long; however we can't use the `compilerHost` above,
|
||||
// Because it only functions until `hostCache` is cleared, while we'll potentially need the functionality to lazily read sourcemap files during
|
||||
// the course of whatever called `synchronizeHostData`
|
||||
sourcemappedFileCache = createSourceFileLikeCache(host);
|
||||
sourceMapper.clearCache();
|
||||
|
||||
// Make sure all the nodes in the program are both bound, and have their parent
|
||||
// pointers set property.
|
||||
@@ -1502,183 +1502,27 @@ namespace ts {
|
||||
return checker.getSymbolAtLocation(node);
|
||||
}
|
||||
|
||||
function toLineColumnOffset(fileName: string, position: number) {
|
||||
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
const file = program.getSourceFile(path) || sourcemappedFileCache.get(path)!; // TODO: GH#18217
|
||||
return file.getLineAndCharacterOfPosition(position);
|
||||
}
|
||||
|
||||
// Sometimes tools can sometimes see the following line as a source mapping url comment, so we mangle it a bit (the [M])
|
||||
const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)$/;
|
||||
const whitespaceOrMapCommentRegExp = /^\s*(\/\/[@#] .*)?$/;
|
||||
const base64UrlRegExp = /^data:(?:application\/json(?:;charset=[uU][tT][fF]-8);base64,([A-Za-z0-9+\/=]+)$)?/;
|
||||
function scanForSourcemapURL(fileName: string) {
|
||||
const mappedFile = sourcemappedFileCache.get(toPath(fileName, currentDirectory, getCanonicalFileName));
|
||||
if (!mappedFile) {
|
||||
return;
|
||||
}
|
||||
const starts = getLineStarts(mappedFile);
|
||||
for (let index = starts.length - 1; index >= 0; index--) {
|
||||
const lineText = mappedFile.text.substring(starts[index], starts[index + 1]);
|
||||
const comment = sourceMapCommentRegExp.exec(lineText);
|
||||
if (comment) {
|
||||
return comment[1];
|
||||
}
|
||||
// If we see a nonwhitespace/map comment-like line, break, to avoid scanning up the entire file
|
||||
else if (!lineText.match(whitespaceOrMapCommentRegExp)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function convertDocumentToSourceMapper(file: { sourceMapper?: sourcemaps.SourceMapper }, contents: string, mapFileName: string) {
|
||||
let maps: sourcemaps.SourceMapData | undefined;
|
||||
try {
|
||||
maps = JSON.parse(contents);
|
||||
}
|
||||
catch {
|
||||
// swallow error
|
||||
}
|
||||
if (!maps || !maps.sources || !maps.file || !maps.mappings) {
|
||||
// obviously invalid map
|
||||
return file.sourceMapper = sourcemaps.identitySourceMapper;
|
||||
}
|
||||
return file.sourceMapper = sourcemaps.decode({
|
||||
readFile: s => host.readFile!(s), // TODO: GH#18217
|
||||
fileExists: s => host.fileExists!(s), // TODO: GH#18217
|
||||
getCanonicalFileName,
|
||||
log,
|
||||
}, mapFileName, maps, program, sourcemappedFileCache);
|
||||
}
|
||||
|
||||
function getSourceMapper(fileName: string, file: { sourceMapper?: sourcemaps.SourceMapper }) {
|
||||
if (!host.readFile || !host.fileExists) {
|
||||
return file.sourceMapper = sourcemaps.identitySourceMapper;
|
||||
}
|
||||
if (file.sourceMapper) {
|
||||
return file.sourceMapper;
|
||||
}
|
||||
let mapFileName = scanForSourcemapURL(fileName);
|
||||
if (mapFileName) {
|
||||
const match = base64UrlRegExp.exec(mapFileName);
|
||||
if (match) {
|
||||
if (match[1]) {
|
||||
const base64Object = match[1];
|
||||
return convertDocumentToSourceMapper(file, base64decode(sys, base64Object), fileName);
|
||||
}
|
||||
// Not a data URL we can parse, skip it
|
||||
mapFileName = undefined;
|
||||
}
|
||||
}
|
||||
const possibleMapLocations: string[] = [];
|
||||
if (mapFileName) {
|
||||
possibleMapLocations.push(mapFileName);
|
||||
}
|
||||
possibleMapLocations.push(fileName + ".map");
|
||||
for (const location of possibleMapLocations) {
|
||||
const mapPath = toPath(location, getDirectoryPath(fileName), getCanonicalFileName);
|
||||
if (host.fileExists(mapPath)) {
|
||||
return convertDocumentToSourceMapper(file, host.readFile(mapPath)!, mapPath); // TODO: GH#18217
|
||||
}
|
||||
}
|
||||
return file.sourceMapper = sourcemaps.identitySourceMapper;
|
||||
}
|
||||
|
||||
function makeGetTargetOfMappedPosition<TIn>(
|
||||
extract: (original: TIn) => sourcemaps.SourceMappableLocation,
|
||||
create: (result: sourcemaps.SourceMappableLocation, unmapped: TIn, original: TIn) => TIn
|
||||
) {
|
||||
return getTargetOfMappedPosition;
|
||||
function getTargetOfMappedPosition(input: TIn, original = input): TIn {
|
||||
const info = extract(input);
|
||||
if (endsWith(info.fileName, Extension.Dts)) {
|
||||
let file: SourceFileLike | undefined = program.getSourceFile(info.fileName);
|
||||
if (!file) {
|
||||
const path = toPath(info.fileName, currentDirectory, getCanonicalFileName);
|
||||
file = sourcemappedFileCache.get(path);
|
||||
}
|
||||
if (!file) {
|
||||
return input;
|
||||
}
|
||||
const mapper = getSourceMapper(info.fileName, file);
|
||||
const newLoc = mapper.getOriginalPosition(info);
|
||||
if (newLoc === info) return input;
|
||||
return getTargetOfMappedPosition(create(newLoc, input, original), original);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
const getTargetOfMappedDeclarationInfo = makeGetTargetOfMappedPosition(
|
||||
(info: DefinitionInfo) => ({ fileName: info.fileName, position: info.textSpan.start }),
|
||||
(newLoc, info, original) => ({
|
||||
containerKind: info.containerKind,
|
||||
containerName: info.containerName,
|
||||
fileName: newLoc.fileName,
|
||||
kind: info.kind,
|
||||
name: info.name,
|
||||
textSpan: {
|
||||
start: newLoc.position,
|
||||
length: info.textSpan.length
|
||||
},
|
||||
originalFileName: original.fileName,
|
||||
originalTextSpan: original.textSpan
|
||||
})
|
||||
);
|
||||
|
||||
function getTargetOfMappedDeclarationFiles(infos: ReadonlyArray<DefinitionInfo> | undefined): DefinitionInfo[] | undefined {
|
||||
return map(infos, d => getTargetOfMappedDeclarationInfo(d));
|
||||
}
|
||||
|
||||
/// Goto definition
|
||||
function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined {
|
||||
synchronizeHostData();
|
||||
return getTargetOfMappedDeclarationFiles(GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position));
|
||||
return GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position);
|
||||
}
|
||||
|
||||
function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined {
|
||||
synchronizeHostData();
|
||||
const result = GoToDefinition.getDefinitionAndBoundSpan(program, getValidSourceFile(fileName), position);
|
||||
if (!result) return result;
|
||||
const mappedDefs = getTargetOfMappedDeclarationFiles(result.definitions);
|
||||
if (mappedDefs === result.definitions) {
|
||||
return result;
|
||||
}
|
||||
return {
|
||||
definitions: mappedDefs,
|
||||
textSpan: result.textSpan
|
||||
};
|
||||
return GoToDefinition.getDefinitionAndBoundSpan(program, getValidSourceFile(fileName), position);
|
||||
}
|
||||
|
||||
function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] | undefined {
|
||||
synchronizeHostData();
|
||||
return getTargetOfMappedDeclarationFiles(GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position));
|
||||
return GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position);
|
||||
}
|
||||
|
||||
/// Goto implementation
|
||||
|
||||
const getTargetOfMappedImplementationLocation = makeGetTargetOfMappedPosition(
|
||||
(info: ImplementationLocation) => ({ fileName: info.fileName, position: info.textSpan.start }),
|
||||
(newLoc, info) => ({
|
||||
fileName: newLoc.fileName,
|
||||
kind: info.kind,
|
||||
displayParts: info.displayParts,
|
||||
textSpan: {
|
||||
start: newLoc.position,
|
||||
length: info.textSpan.length
|
||||
},
|
||||
originalFileName: info.fileName,
|
||||
originalTextSpan: info.textSpan
|
||||
})
|
||||
);
|
||||
|
||||
function getTargetOfMappedImplementationLocations(infos: ReadonlyArray<ImplementationLocation> | undefined): ImplementationLocation[] | undefined {
|
||||
return map(infos, d => getTargetOfMappedImplementationLocation(d));
|
||||
}
|
||||
|
||||
function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] | undefined {
|
||||
synchronizeHostData();
|
||||
return getTargetOfMappedImplementationLocations(FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position));
|
||||
return FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position);
|
||||
}
|
||||
|
||||
/// References and Occurrences
|
||||
@@ -1735,10 +1579,8 @@ namespace ts {
|
||||
return FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position);
|
||||
}
|
||||
|
||||
/// NavigateTo
|
||||
function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): NavigateToItem[] {
|
||||
synchronizeHostData();
|
||||
|
||||
const sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles();
|
||||
return NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles);
|
||||
}
|
||||
@@ -2289,7 +2131,8 @@ namespace ts {
|
||||
getProgram,
|
||||
getApplicableRefactors,
|
||||
getEditsForRefactor,
|
||||
toLineColumnOffset
|
||||
toLineColumnOffset: sourceMapper.toLineColumnOffset,
|
||||
getSourceMapper: () => sourceMapper,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
// Sometimes tools can sometimes see the following line as a source mapping url comment, so we mangle it a bit (the [M])
|
||||
const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)\s*$/;
|
||||
const whitespaceOrMapCommentRegExp = /^\s*(\/\/[@#] .*)?$/;
|
||||
const base64UrlRegExp = /^data:(?:application\/json(?:;charset=[uU][tT][fF]-8);base64,([A-Za-z0-9+\/=]+)$)?/;
|
||||
|
||||
export interface SourceMapper {
|
||||
toLineColumnOffset(fileName: string, position: number): LineAndCharacter;
|
||||
tryGetOriginalLocation(info: sourcemaps.SourceMappableLocation): sourcemaps.SourceMappableLocation | undefined;
|
||||
clearCache(): void;
|
||||
}
|
||||
|
||||
export function getSourceMapper(
|
||||
getCanonicalFileName: GetCanonicalFileName,
|
||||
currentDirectory: string,
|
||||
log: (message: string) => void,
|
||||
host: LanguageServiceHost,
|
||||
getProgram: () => Program,
|
||||
): SourceMapper {
|
||||
let sourcemappedFileCache: SourceFileLikeCache;
|
||||
return { tryGetOriginalLocation, toLineColumnOffset, clearCache };
|
||||
|
||||
function scanForSourcemapURL(fileName: string) {
|
||||
const mappedFile = sourcemappedFileCache.get(toPath(fileName, currentDirectory, getCanonicalFileName));
|
||||
if (!mappedFile) {
|
||||
return;
|
||||
}
|
||||
const starts = getLineStarts(mappedFile);
|
||||
for (let index = starts.length - 1; index >= 0; index--) {
|
||||
const lineText = mappedFile.text.substring(starts[index], starts[index + 1]);
|
||||
const comment = sourceMapCommentRegExp.exec(lineText);
|
||||
if (comment) {
|
||||
return comment[1];
|
||||
}
|
||||
// If we see a non-whitespace/map comment-like line, break, to avoid scanning up the entire file
|
||||
else if (!lineText.match(whitespaceOrMapCommentRegExp)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function convertDocumentToSourceMapper(file: { sourceMapper?: sourcemaps.SourceMapper }, contents: string, mapFileName: string) {
|
||||
let maps: sourcemaps.SourceMapData | undefined;
|
||||
try {
|
||||
maps = JSON.parse(contents);
|
||||
}
|
||||
catch {
|
||||
// swallow error
|
||||
}
|
||||
if (!maps || !maps.sources || !maps.file || !maps.mappings) {
|
||||
// obviously invalid map
|
||||
return file.sourceMapper = sourcemaps.identitySourceMapper;
|
||||
}
|
||||
return file.sourceMapper = sourcemaps.decode({
|
||||
readFile: s => host.readFile!(s), // TODO: GH#18217
|
||||
fileExists: s => host.fileExists!(s), // TODO: GH#18217
|
||||
getCanonicalFileName,
|
||||
log,
|
||||
}, mapFileName, maps, getProgram(), sourcemappedFileCache);
|
||||
}
|
||||
|
||||
function getSourceMapper(fileName: string, file: SourceFileLike): sourcemaps.SourceMapper {
|
||||
if (!host.readFile || !host.fileExists) {
|
||||
return file.sourceMapper = sourcemaps.identitySourceMapper;
|
||||
}
|
||||
if (file.sourceMapper) {
|
||||
return file.sourceMapper;
|
||||
}
|
||||
let mapFileName = scanForSourcemapURL(fileName);
|
||||
if (mapFileName) {
|
||||
const match = base64UrlRegExp.exec(mapFileName);
|
||||
if (match) {
|
||||
if (match[1]) {
|
||||
const base64Object = match[1];
|
||||
return convertDocumentToSourceMapper(file, base64decode(sys, base64Object), fileName);
|
||||
}
|
||||
// Not a data URL we can parse, skip it
|
||||
mapFileName = undefined;
|
||||
}
|
||||
}
|
||||
const possibleMapLocations: string[] = [];
|
||||
if (mapFileName) {
|
||||
possibleMapLocations.push(mapFileName);
|
||||
}
|
||||
possibleMapLocations.push(fileName + ".map");
|
||||
for (const location of possibleMapLocations) {
|
||||
const mapPath = toPath(location, getDirectoryPath(fileName), getCanonicalFileName);
|
||||
if (host.fileExists(mapPath)) {
|
||||
return convertDocumentToSourceMapper(file, host.readFile(mapPath)!, mapPath); // TODO: GH#18217
|
||||
}
|
||||
}
|
||||
return file.sourceMapper = sourcemaps.identitySourceMapper;
|
||||
}
|
||||
|
||||
function tryGetOriginalLocation(info: sourcemaps.SourceMappableLocation): sourcemaps.SourceMappableLocation | undefined {
|
||||
if (!isDeclarationFileName(info.fileName)) return undefined;
|
||||
|
||||
const file = getProgram().getSourceFile(info.fileName) || sourcemappedFileCache.get(toPath(info.fileName, currentDirectory, getCanonicalFileName));
|
||||
if (!file) return undefined;
|
||||
const newLoc = getSourceMapper(info.fileName, file).getOriginalPosition(info);
|
||||
return newLoc === info ? undefined : tryGetOriginalLocation(newLoc) || newLoc;
|
||||
}
|
||||
|
||||
function toLineColumnOffset(fileName: string, position: number): LineAndCharacter {
|
||||
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
const file = getProgram().getSourceFile(path) || sourcemappedFileCache.get(path)!; // TODO: GH#18217
|
||||
return file.getLineAndCharacterOfPosition(position);
|
||||
}
|
||||
|
||||
function clearCache(): void {
|
||||
sourcemappedFileCache = createSourceFileLikeCache(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@
|
||||
"preProcess.ts",
|
||||
"rename.ts",
|
||||
"signatureHelp.ts",
|
||||
"sourcemaps.ts",
|
||||
"suggestionDiagnostics.ts",
|
||||
"symbolDisplay.ts",
|
||||
"transpile.ts",
|
||||
|
||||
@@ -334,6 +334,8 @@ namespace ts {
|
||||
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined;
|
||||
|
||||
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
|
||||
/** @internal */
|
||||
getSourceMapper(): SourceMapper;
|
||||
|
||||
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray<CodeFixAction>;
|
||||
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
|
||||
|
||||
@@ -1417,6 +1417,13 @@ namespace ts {
|
||||
changes.insertNodeAtTopOfFile(sourceFile, importDecl, /*blankLineBetween*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
export function textSpansEqual(a: TextSpan | undefined, b: TextSpan | undefined): boolean {
|
||||
return !!a && !!b && a.start === b.start && a.length === b.length;
|
||||
}
|
||||
export function documentSpansEqual(a: DocumentSpan, b: DocumentSpan): boolean {
|
||||
return a.fileName === b.fileName && textSpansEqual(a.textSpan, b.textSpan);
|
||||
}
|
||||
}
|
||||
|
||||
// Display-part writer helpers
|
||||
|
||||
@@ -415,7 +415,7 @@ namespace ts.projectSystem {
|
||||
checkArray("Open files", arrayFrom(projectService.openFiles.keys(), path => projectService.getScriptInfoForPath(path as Path)!.fileName), expectedFiles.map(file => file.path));
|
||||
}
|
||||
|
||||
function protocolLocationFromSubstring(str: string, substring: string) {
|
||||
function protocolLocationFromSubstring(str: string, substring: string): protocol.Location {
|
||||
const start = str.indexOf(substring);
|
||||
Debug.assert(start !== -1);
|
||||
return protocolToLocation(str)(start);
|
||||
@@ -427,21 +427,36 @@ namespace ts.projectSystem {
|
||||
return { line: x.line + 1, offset: x.character + 1 };
|
||||
};
|
||||
}
|
||||
function protocolTextSpanFromSubstring(str: string, substring: string): protocol.TextSpan {
|
||||
const span = textSpanFromSubstring(str, substring);
|
||||
function protocolTextSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): protocol.TextSpan {
|
||||
const span = textSpanFromSubstring(str, substring, options);
|
||||
const toLocation = protocolToLocation(str);
|
||||
return { start: toLocation(span.start), end: toLocation(span.start + span.length) };
|
||||
return { start: toLocation(span.start), end: toLocation(textSpanEnd(span)) };
|
||||
}
|
||||
function textSpanFromSubstring(str: string, substring: string): TextSpan {
|
||||
const start = str.indexOf(substring);
|
||||
function textSpanFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): TextSpan {
|
||||
const start = nthIndexOf(str, substring, options ? options.index : 0);
|
||||
Debug.assert(start !== -1);
|
||||
return createTextSpan(start, substring.length);
|
||||
}
|
||||
function protocolFileLocationFromSubstring(file: File, substring: string): protocol.FileLocationRequestArgs {
|
||||
return { file: file.path, ...protocolLocationFromSubstring(file.content, substring) };
|
||||
}
|
||||
function protocolFileSpanFromSubstring(file: File, substring: string): protocol.FileSpan {
|
||||
return { file: file.path, ...protocolTextSpanFromSubstring(file.content, substring) };
|
||||
function protocolFileSpanFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions) {
|
||||
return { file: file.path, ...protocolTextSpanFromSubstring(file.content, substring, options) };
|
||||
}
|
||||
function documentSpanFromSubstring(file: File, substring: string, options?: SpanFromSubstringOptions): DocumentSpan {
|
||||
return { fileName: file.path, textSpan: textSpanFromSubstring(file.content, substring, options) };
|
||||
}
|
||||
interface SpanFromSubstringOptions {
|
||||
readonly index: number;
|
||||
}
|
||||
|
||||
function nthIndexOf(str: string, substr: string, n: number): number {
|
||||
let index = -1;
|
||||
for (; n >= 0; n--) {
|
||||
index = str.indexOf(substr, index + 1);
|
||||
if (index === -1) return -1;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -496,10 +511,14 @@ namespace ts.projectSystem {
|
||||
};
|
||||
}
|
||||
|
||||
export function openFilesForSession(files: ReadonlyArray<File>, session: server.Session): void {
|
||||
export function executeSessionRequest<TRequest extends protocol.Request, TResponse extends protocol.Response>(session: server.Session, command: TRequest["command"], args: TRequest["arguments"]): TResponse["body"] {
|
||||
return session.executeCommand(makeSessionRequest(command, args)).response as TResponse["body"];
|
||||
}
|
||||
|
||||
export function openFilesForSession(files: ReadonlyArray<File | { readonly file: File | string, readonly projectRootPath: string }>, session: server.Session): void {
|
||||
for (const file of files) {
|
||||
const request = makeSessionRequest<protocol.OpenRequestArgs>(CommandNames.Open, { file: file.path });
|
||||
session.executeCommand(request);
|
||||
session.executeCommand(makeSessionRequest<protocol.OpenRequestArgs>(CommandNames.Open,
|
||||
"projectRootPath" in file ? { file: typeof file.file === "string" ? file.file : file.file.path, projectRootPath: file.projectRootPath } : { file: file.path }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3385,7 +3404,7 @@ namespace ts.projectSystem {
|
||||
host.reloadFS(files.map(f => f === fileSubA ? fileA : f));
|
||||
host.checkTimeoutQueueLength(2);
|
||||
|
||||
closeFile(fileSubA);
|
||||
closeFilesForSession([fileSubA], session);
|
||||
// This should cancel existing updates and schedule new ones
|
||||
host.checkTimeoutQueueLength(2);
|
||||
checkNumberOfProjects(services, { configuredProjects: 1 });
|
||||
@@ -3405,7 +3424,7 @@ namespace ts.projectSystem {
|
||||
// file is deleted but watches are not yet invoked
|
||||
const originalFileExists = host.fileExists;
|
||||
host.fileExists = s => s === fileA.path ? false : originalFileExists.call(host, s);
|
||||
closeFile(fileA);
|
||||
closeFilesForSession([fileA], session);
|
||||
host.checkTimeoutQueueLength(2); // Update configured project and projects for open file
|
||||
checkProjectActualFiles(services.configuredProjects.get(config.path)!, filesWithFileA.map(f => f.path));
|
||||
|
||||
@@ -3453,23 +3472,7 @@ namespace ts.projectSystem {
|
||||
assert.isFalse(hasErrorMsg());
|
||||
|
||||
function openFile(file: File) {
|
||||
session.executeCommandSeq<protocol.OpenRequest>({
|
||||
command: protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
file: file.path,
|
||||
fileContent: file.content,
|
||||
projectRootPath
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function closeFile(file: File) {
|
||||
session.executeCommandSeq<protocol.CloseRequest>({
|
||||
command: protocol.CommandTypes.Close,
|
||||
arguments: {
|
||||
file: file.path
|
||||
}
|
||||
});
|
||||
openFilesForSession([{ file, projectRootPath }], session);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -3686,40 +3689,17 @@ namespace ts.projectSystem {
|
||||
const files = [libFile, app, serverUtilities, backendTest];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { useInferredProjectPerProjectRoot: true, canUseEvents: true });
|
||||
session.executeCommandSeq<protocol.OpenRequest>({
|
||||
command: protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
file: app.path,
|
||||
projectRootPath: projectRoot
|
||||
}
|
||||
});
|
||||
openFilesForSession([{ file: app, projectRootPath: projectRoot }], session);
|
||||
const service = session.getProjectService();
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
const project = service.inferredProjects[0];
|
||||
checkProjectActualFiles(project, [libFile.path, app.path]);
|
||||
session.executeCommandSeq<protocol.OpenRequest>({
|
||||
command: protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
file: backendTest.path,
|
||||
projectRootPath: projectRoot
|
||||
}
|
||||
});
|
||||
openFilesForSession([{ file: backendTest, projectRootPath: projectRoot }], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, files.map(f => f.path));
|
||||
checkErrors([backendTest.path, app.path]);
|
||||
session.executeCommandSeq<protocol.CloseRequest>({
|
||||
command: protocol.CommandTypes.Close,
|
||||
arguments: {
|
||||
file: backendTest.path
|
||||
}
|
||||
});
|
||||
session.executeCommandSeq<protocol.OpenRequest>({
|
||||
command: protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
file: serverUtilities.path,
|
||||
projectRootPath: projectRoot
|
||||
}
|
||||
});
|
||||
closeFilesForSession([backendTest], session);
|
||||
openFilesForSession([{ file: serverUtilities.path, projectRootPath: projectRoot }], session);
|
||||
checkErrors([serverUtilities.path, app.path]);
|
||||
|
||||
function checkErrors(openFiles: [string, string]) {
|
||||
@@ -7886,72 +7866,42 @@ namespace ts.projectSystem {
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host);
|
||||
const projectService = session.getProjectService();
|
||||
session.executeCommandSeq<protocol.OpenRequest>({
|
||||
command: protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
file: aFile.path,
|
||||
projectRootPath: folderA
|
||||
}
|
||||
});
|
||||
session.executeCommandSeq<protocol.OpenRequest>({
|
||||
command: protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
file: bFile.path,
|
||||
projectRootPath: folderB
|
||||
}
|
||||
});
|
||||
|
||||
session.executeCommandSeq<protocol.OpenRequest>({
|
||||
command: protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
file: aFc,
|
||||
projectRootPath: folderA
|
||||
}
|
||||
});
|
||||
session.executeCommandSeq<protocol.OpenRequest>({
|
||||
command: protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
file: bFc,
|
||||
projectRootPath: folderB
|
||||
}
|
||||
});
|
||||
openFilesForSession(
|
||||
[
|
||||
{ file: aFile, projectRootPath: folderA },
|
||||
{ file: bFile, projectRootPath: folderB },
|
||||
{ file: aFc, projectRootPath: folderA },
|
||||
{ file: bFc, projectRootPath: folderB },
|
||||
],
|
||||
session);
|
||||
checkNumberOfProjects(projectService, { configuredProjects: 2 });
|
||||
assert.isDefined(projectService.configuredProjects.get(aTsconfig.path));
|
||||
assert.isDefined(projectService.configuredProjects.get(bTsconfig.path));
|
||||
|
||||
verifyRenameResponse(session.executeCommandSeq<protocol.RenameRequest>({
|
||||
command: protocol.CommandTypes.Rename,
|
||||
arguments: {
|
||||
file: aFc,
|
||||
line: 1,
|
||||
offset: 14,
|
||||
findInStrings: false,
|
||||
findInComments: false
|
||||
}
|
||||
}).response as protocol.RenameResponseBody);
|
||||
const response = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, { file: aFc, ...protocolLocationFromSubstring(cFile.content, "C") });
|
||||
|
||||
function verifyRenameResponse({ info, locs }: protocol.RenameResponseBody) {
|
||||
assert.isTrue(info.canRename);
|
||||
assert.equal(locs.length, 4);
|
||||
verifyLocations(0, aFile.path, aFc);
|
||||
verifyLocations(2, bFile.path, bFc);
|
||||
|
||||
function verifyLocations(locStartIndex: number, firstFile: string, secondFile: string) {
|
||||
assert.deepEqual(locs[locStartIndex], {
|
||||
file: firstFile,
|
||||
locs: [
|
||||
{ start: { line: 1, offset: 39 }, end: { line: 1, offset: 40 } },
|
||||
{ start: { line: 1, offset: 9 }, end: { line: 1, offset: 10 } }
|
||||
]
|
||||
});
|
||||
assert.deepEqual(locs[locStartIndex + 1], {
|
||||
file: secondFile,
|
||||
locs: [
|
||||
{ start: { line: 1, offset: 14 }, end: { line: 1, offset: 15 } }
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
assert.equal(aFile.content, bFile.content);
|
||||
const abLocs: protocol.TextSpan[] = [
|
||||
protocolTextSpanFromSubstring(aFile.content, "C"),
|
||||
protocolTextSpanFromSubstring(aFile.content, "C", { index: 1 }),
|
||||
];
|
||||
const cLocs: protocol.TextSpan[] = [protocolTextSpanFromSubstring(cFile.content, "C")];
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response, {
|
||||
info: {
|
||||
canRename: true,
|
||||
displayName: "C",
|
||||
fullDisplayName: '"/users/username/projects/a/c/fc".C',
|
||||
kind: ScriptElementKind.constElement,
|
||||
kindModifiers: ScriptElementKindModifier.exportedModifier,
|
||||
localizedErrorMessage: undefined,
|
||||
},
|
||||
locs: [
|
||||
{ file: aFc, locs: cLocs },
|
||||
{ file: aFile.path, locs: abLocs },
|
||||
{ file: bFc, locs: cLocs },
|
||||
{ file: bFile.path, locs: abLocs },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
describe("module resolution when symlinked folder contents change and resolve modules", () => {
|
||||
@@ -8948,93 +8898,323 @@ export function Test2() {
|
||||
function makeSampleProjects() {
|
||||
const aTs: File = {
|
||||
path: "/a/a.ts",
|
||||
content: "export function fnA() {}",
|
||||
content: "export function fnA() {}\nexport interface IfaceA {}\nexport const instanceA: IfaceA = {};",
|
||||
};
|
||||
const aTsconfig: File = {
|
||||
path: "/a/tsconfig.json",
|
||||
content: `{
|
||||
"compilerOptions": {
|
||||
"outDir": "bin",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"composite": true,
|
||||
}
|
||||
}`,
|
||||
const compilerOptions: CompilerOptions = {
|
||||
outDir: "bin",
|
||||
declaration: true,
|
||||
declarationMap: true,
|
||||
composite: true,
|
||||
};
|
||||
const configContent = JSON.stringify({ compilerOptions });
|
||||
const aTsconfig: File = { path: "/a/tsconfig.json", content: configContent };
|
||||
|
||||
const aDtsMapContent: SourceMapSection = {
|
||||
version: 3,
|
||||
file: "a.d.ts",
|
||||
sourceRoot: "",
|
||||
sources: ["../a.ts"],
|
||||
names: [],
|
||||
mappings: "AAAA,wBAAgB,GAAG,SAAK;AACxB,MAAM,WAAW,MAAM;CAAG;AAC1B,eAAO,MAAM,SAAS,EAAE,MAAW,CAAC"
|
||||
};
|
||||
const aDtsMap: File = {
|
||||
path: "/a/bin/a.d.ts.map",
|
||||
content: JSON.stringify(aDtsMapContent),
|
||||
};
|
||||
const aDts: File = {
|
||||
path: "/a/bin/a.d.ts",
|
||||
// Need to mangle the sourceMappingURL part or it breaks the build
|
||||
content: `export declare function fnA(): void;\nexport interface IfaceA {\n}\nexport declare const instanceA: IfaceA;\n//# source${""}MappingURL=a.d.ts.map`,
|
||||
};
|
||||
|
||||
const bTs: File = {
|
||||
path: "/b/b.ts",
|
||||
content: 'import { fnA } from "../a/a";\nexport function fnB() { fnA(); }',
|
||||
content: "export function fnB() {}",
|
||||
};
|
||||
const bTsconfig: File = {
|
||||
path: "/b/tsconfig.json",
|
||||
content: `{
|
||||
"compilerOptions": {
|
||||
"outDir": "bin",
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../a" }
|
||||
]
|
||||
}`,
|
||||
const bTsconfig: File = { path: "/b/tsconfig.json", content: configContent };
|
||||
|
||||
const bDtsMapContent: SourceMapSection = {
|
||||
version: 3,
|
||||
file: "b.d.ts",
|
||||
sourceRoot: "",
|
||||
sources: ["../b.ts"],
|
||||
names: [],
|
||||
mappings: "AAAA,wBAAgB,GAAG,SAAK",
|
||||
};
|
||||
const bDtsMap: File = {
|
||||
path: "/b/bin/b.d.ts.map",
|
||||
content: JSON.stringify(bDtsMapContent),
|
||||
};
|
||||
const bDts: File = {
|
||||
// Need to mangle the sourceMappingURL part or it breaks the build
|
||||
path: "/b/bin/b.d.ts",
|
||||
content: `export declare function fnB(): void;\n//# source${""}MappingURL=b.d.ts.map`,
|
||||
};
|
||||
|
||||
const host = createServerHost([aTs, aTsconfig, bTs, bTsconfig]);
|
||||
const userTs: File = {
|
||||
path: "/user/user.ts",
|
||||
content: 'import { fnA, instanceA } from "../a/bin/a";\nimport { fnB } from "../b/bin/b";\nexport function fnUser() { fnA(); fnB(); instanceA; }',
|
||||
};
|
||||
|
||||
const host = createServerHost([aTs, aTsconfig, aDtsMap, aDts, bTsconfig, bTs, bDtsMap, bDts, userTs]);
|
||||
const session = createSession(host);
|
||||
|
||||
writeDeclarationFiles(aTs, host, session, [
|
||||
{ name: "/a/bin/a.d.ts.map", text: '{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["../a.ts"],"names":[],"mappings":"AAAA,wBAAgB,GAAG,SAAK"}' },
|
||||
// Need to mangle the sourceMappingURL part or it breaks the build
|
||||
{ name: "/a/bin/a.d.ts", text: `export declare function fnA(): void;\n//# source${""}MappingURL=a.d.ts.map` },
|
||||
]);
|
||||
checkDeclarationFiles(aTs, session, [aDtsMap, aDts]);
|
||||
checkDeclarationFiles(bTs, session, [bDtsMap, bDts]);
|
||||
|
||||
return { session, aTs, bTs };
|
||||
// Testing what happens if we delete the original sources.
|
||||
host.removeFile(bTs.path);
|
||||
|
||||
openFilesForSession([userTs], session);
|
||||
|
||||
return { session, aTs, bDts, userTs };
|
||||
}
|
||||
|
||||
describe("tsserverProjectSystem project references", () => {
|
||||
it("goToDefinition", () => {
|
||||
const { session, aTs, bTs } = makeSampleProjects();
|
||||
const { session, aTs, userTs } = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.DefinitionRequest, protocol.DefinitionResponse>(session, protocol.CommandTypes.Definition, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual(response, [protocolFileSpanFromSubstring(aTs, "fnA")]);
|
||||
});
|
||||
|
||||
openFilesForSession([bTs], session);
|
||||
it("getDefinitionAndBoundSpan", () => {
|
||||
const { session, aTs, userTs } = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.DefinitionAndBoundSpanRequest, protocol.DefinitionAndBoundSpanResponse>(session, protocol.CommandTypes.DefinitionAndBoundSpan, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual(response, {
|
||||
textSpan: protocolTextSpanFromSubstring(userTs.content, "fnA", { index: 1 }),
|
||||
definitions: [protocolFileSpanFromSubstring(aTs, "fnA")],
|
||||
});
|
||||
});
|
||||
|
||||
const definitionRequest = makeSessionRequest<protocol.FileLocationRequestArgs>(CommandNames.Definition, protocolFileLocationFromSubstring(bTs, "fnA()"));
|
||||
const definitionResponse = session.executeCommand(definitionRequest).response as protocol.DefinitionResponse["body"];
|
||||
it("goToType", () => {
|
||||
const { session, aTs, userTs } = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.TypeDefinitionRequest, protocol.TypeDefinitionResponse>(session, protocol.CommandTypes.TypeDefinition, protocolFileLocationFromSubstring(userTs, "instanceA"));
|
||||
assert.deepEqual(response, [protocolFileSpanFromSubstring(aTs, "IfaceA")]);
|
||||
});
|
||||
|
||||
assert.deepEqual(definitionResponse, [protocolFileSpanFromSubstring(aTs, "fnA")]);
|
||||
it("goToImplementation", () => {
|
||||
const { session, aTs, userTs } = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.ImplementationRequest, protocol.ImplementationResponse>(session, protocol.CommandTypes.Implementation, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual(response, [protocolFileSpanFromSubstring(aTs, "fnA")]);
|
||||
});
|
||||
|
||||
it("goToDefinition -- target does not exist", () => {
|
||||
const { session, bDts, userTs } = 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")]);
|
||||
});
|
||||
|
||||
it("navigateTo", () => {
|
||||
const { session, bTs } = makeSampleProjects();
|
||||
|
||||
openFilesForSession([bTs], session);
|
||||
|
||||
const navtoRequest = makeSessionRequest<protocol.NavtoRequestArgs>(CommandNames.Navto, { file: bTs.path, searchValue: "fn" });
|
||||
const navtoResponse = session.executeCommand(navtoRequest).response as protocol.NavtoResponse["body"];
|
||||
|
||||
assert.deepEqual<ReadonlyArray<protocol.NavtoItem> | undefined>(navtoResponse, [
|
||||
// TODO: First result should be from a.ts, not a.d.ts
|
||||
const { session, aTs, bDts, userTs } = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.NavtoRequest, protocol.NavtoResponse>(session, CommandNames.Navto, { file: userTs.path, searchValue: "fn" });
|
||||
assert.deepEqual<ReadonlyArray<protocol.NavtoItem> | undefined>(response, [
|
||||
{
|
||||
file: "/a/bin/a.d.ts",
|
||||
start: { line: 1, offset: 1 },
|
||||
end: { line: 1, offset: 37 },
|
||||
name: "fnA",
|
||||
...protocolFileSpanFromSubstring(bDts, "export declare function fnB(): void;"),
|
||||
name: "fnB",
|
||||
matchKind: "prefix",
|
||||
isCaseSensitive: true,
|
||||
kind: ScriptElementKind.functionElement,
|
||||
kindModifiers: "export,declare",
|
||||
},
|
||||
{
|
||||
...protocolFileSpanFromSubstring(bTs, "export function fnB() { fnA(); }"),
|
||||
name: "fnB",
|
||||
...protocolFileSpanFromSubstring(userTs, "export function fnUser() { fnA(); fnB(); instanceA; }"),
|
||||
name: "fnUser",
|
||||
matchKind: "prefix",
|
||||
isCaseSensitive: true,
|
||||
kind: ScriptElementKind.functionElement,
|
||||
kindModifiers: "export",
|
||||
},
|
||||
{
|
||||
...protocolFileSpanFromSubstring(aTs, "export function fnA() {}"),
|
||||
name: "fnA",
|
||||
matchKind: "prefix",
|
||||
isCaseSensitive: true,
|
||||
kind: ScriptElementKind.functionElement,
|
||||
kindModifiers: "export",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("findAllReferences", () => {
|
||||
const { session, aTs, userTs } = makeSampleProjects();
|
||||
|
||||
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(session, protocol.CommandTypes.References, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual<protocol.ReferencesResponseBody | undefined>(response, {
|
||||
refs: [
|
||||
makeReferenceItem(userTs, /*isDefinition*/ true, "fnA"),
|
||||
makeReferenceItem(userTs, /*isDefinition*/ false, "fnA", { index: 1 }),
|
||||
makeReferenceItem(aTs, /*isDefinition*/ true, "fnA"),
|
||||
],
|
||||
symbolName: "fnA",
|
||||
symbolStartOffset: protocolLocationFromSubstring(userTs.content, "fnA()").offset,
|
||||
symbolDisplayString: "(alias) fnA(): void\nimport fnA",
|
||||
});
|
||||
});
|
||||
|
||||
it("findAllReferencesFull", () => {
|
||||
const { session, aTs, userTs } = makeSampleProjects();
|
||||
|
||||
interface ReferencesFullRequest extends protocol.FileLocationRequest { command: protocol.CommandTypes.ReferencesFull; }
|
||||
interface ReferencesFullResponse extends protocol.Response { body: ReadonlyArray<ReferencedSymbol>; }
|
||||
const responseFull = executeSessionRequest<ReferencesFullRequest, ReferencesFullResponse>(session, protocol.CommandTypes.ReferencesFull, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
|
||||
function fnAVoid(kind: SymbolDisplayPartKind): SymbolDisplayPart[] {
|
||||
return [
|
||||
keywordPart(SyntaxKind.FunctionKeyword),
|
||||
spacePart(),
|
||||
displayPart("fnA", kind),
|
||||
punctuationPart(SyntaxKind.OpenParenToken),
|
||||
punctuationPart(SyntaxKind.CloseParenToken),
|
||||
punctuationPart(SyntaxKind.ColonToken),
|
||||
spacePart(),
|
||||
keywordPart(SyntaxKind.VoidKeyword),
|
||||
];
|
||||
}
|
||||
assert.deepEqual<ReadonlyArray<ReferencedSymbol>>(responseFull, [
|
||||
{
|
||||
definition: {
|
||||
...documentSpanFromSubstring(userTs, "fnA"),
|
||||
kind: ScriptElementKind.alias,
|
||||
name: "(alias) function fnA(): void\nimport fnA",
|
||||
containerKind: ScriptElementKind.unknown,
|
||||
containerName: "",
|
||||
displayParts: [
|
||||
punctuationPart(SyntaxKind.OpenParenToken),
|
||||
textPart("alias"),
|
||||
punctuationPart(SyntaxKind.CloseParenToken),
|
||||
spacePart(),
|
||||
...fnAVoid(SymbolDisplayPartKind.aliasName),
|
||||
lineBreakPart(),
|
||||
keywordPart(SyntaxKind.ImportKeyword),
|
||||
spacePart(),
|
||||
displayPart("fnA", SymbolDisplayPartKind.aliasName),
|
||||
],
|
||||
},
|
||||
references: [
|
||||
makeReferenceEntry(userTs, /*isDefinition*/ true, "fnA"),
|
||||
makeReferenceEntry(userTs, /*isDefinition*/ false, "fnA", { index: 1 }),
|
||||
],
|
||||
},
|
||||
{
|
||||
definition: {
|
||||
...documentSpanFromSubstring(aTs, "fnA"),
|
||||
kind: ScriptElementKind.functionElement,
|
||||
name: "function fnA(): void",
|
||||
containerKind: ScriptElementKind.unknown,
|
||||
containerName: "",
|
||||
displayParts: fnAVoid(SymbolDisplayPartKind.functionName),
|
||||
},
|
||||
references: [
|
||||
makeReferenceEntry(aTs, /*isDefinition*/ true, "fnA"),
|
||||
],
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
it("findAllReferences -- target does not exist", () => {
|
||||
const { session, bDts, userTs } = makeSampleProjects();
|
||||
|
||||
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(session, protocol.CommandTypes.References, protocolFileLocationFromSubstring(userTs, "fnB()"));
|
||||
assert.deepEqual<protocol.ReferencesResponseBody | undefined>(response, {
|
||||
refs: [
|
||||
makeReferenceItem(userTs, /*isDefinition*/ true, "fnB"),
|
||||
makeReferenceItem(userTs, /*isDefinition*/ false, "fnB", { index: 1 }),
|
||||
makeReferenceItem(bDts, /*isDefinition*/ true, "fnB"),
|
||||
],
|
||||
symbolName: "fnB",
|
||||
symbolStartOffset: protocolLocationFromSubstring(userTs.content, "fnB()").offset,
|
||||
symbolDisplayString: "(alias) fnB(): void\nimport fnB",
|
||||
});
|
||||
});
|
||||
|
||||
it("renameLocations", () => {
|
||||
const { session, aTs, userTs } = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response, {
|
||||
info: {
|
||||
canRename: true,
|
||||
displayName: "fnA",
|
||||
fullDisplayName: "fnA",
|
||||
kind: ScriptElementKind.alias,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
localizedErrorMessage: undefined,
|
||||
},
|
||||
locs: [
|
||||
{
|
||||
file: userTs.path,
|
||||
locs: [
|
||||
protocolTextSpanFromSubstring(userTs.content, "fnA"),
|
||||
protocolTextSpanFromSubstring(userTs.content, "fnA", { index: 1 }),
|
||||
],
|
||||
},
|
||||
{
|
||||
file: aTs.path,
|
||||
locs: [protocolTextSpanFromSubstring(aTs.content, "fnA")],
|
||||
}
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("renameLocationsFull", () => {
|
||||
const { session, aTs, userTs } = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.RenameFullRequest, protocol.RenameFullResponse>(session, protocol.CommandTypes.RenameLocationsFull, protocolFileLocationFromSubstring(userTs, "fnA()"));
|
||||
assert.deepEqual<ReadonlyArray<RenameLocation>>(response, [
|
||||
documentSpanFromSubstring(userTs, "fnA"),
|
||||
documentSpanFromSubstring(userTs, "fnA", { index: 1 }),
|
||||
documentSpanFromSubstring(aTs, "fnA"),
|
||||
]);
|
||||
});
|
||||
|
||||
it("renameLocations -- target does not exist", () => {
|
||||
const { session, bDts, userTs } = makeSampleProjects();
|
||||
const response = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(userTs, "fnB()"));
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response, {
|
||||
info: {
|
||||
canRename: true,
|
||||
displayName: "fnB",
|
||||
fullDisplayName: "fnB",
|
||||
kind: ScriptElementKind.alias,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
localizedErrorMessage: undefined,
|
||||
},
|
||||
locs: [
|
||||
{
|
||||
file: userTs.path,
|
||||
locs: [
|
||||
protocolTextSpanFromSubstring(userTs.content, "fnB"),
|
||||
protocolTextSpanFromSubstring(userTs.content, "fnB", { index: 1 }),
|
||||
],
|
||||
},
|
||||
{
|
||||
file: bDts.path,
|
||||
locs: [protocolTextSpanFromSubstring(bDts.content, "fnB")],
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
function writeDeclarationFiles(file: File, host: TestServerHost, session: TestSession, expectedFiles: ReadonlyArray<{ readonly name: string, readonly text: string }>): void {
|
||||
function makeReferenceItem(file: File, isDefinition: boolean, text: string, options?: SpanFromSubstringOptions): protocol.ReferencesResponseItem {
|
||||
return {
|
||||
...protocolFileSpanFromSubstring(file, text, options),
|
||||
isDefinition,
|
||||
isWriteAccess: isDefinition,
|
||||
lineText: text,
|
||||
};
|
||||
}
|
||||
|
||||
function makeReferenceEntry(file: File, isDefinition: boolean, text: string, options?: SpanFromSubstringOptions): ReferenceEntry {
|
||||
return {
|
||||
...documentSpanFromSubstring(file, text, options),
|
||||
isDefinition,
|
||||
isWriteAccess: isDefinition,
|
||||
isInString: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
function checkDeclarationFiles(file: File, session: TestSession, expectedFiles: ReadonlyArray<File>): void {
|
||||
openFilesForSession([file], session);
|
||||
const project = Debug.assertDefined(session.getProjectService().getDefaultProjectForFile(file.path as server.NormalizedPath, /*ensureProject*/ false));
|
||||
const program = project.getCurrentProgram();
|
||||
@@ -9042,12 +9222,6 @@ export function Test2() {
|
||||
closeFilesForSession([file], session);
|
||||
|
||||
Debug.assert(!output.emitSkipped);
|
||||
assert.deepEqual(output.outputFiles, expectedFiles.map(e => ({ ...e, writeByteOrderMark: false })));
|
||||
|
||||
for (const { name, text } of output.outputFiles) {
|
||||
const directory: Folder = { path: getDirectoryPath(name) };
|
||||
host.ensureFileOrFolder(directory);
|
||||
host.writeFile(name, text);
|
||||
}
|
||||
assert.deepEqual(output.outputFiles, expectedFiles.map((e): OutputFile => ({ name: e.path, text: e.content, writeByteOrderMark: false })));
|
||||
}
|
||||
}
|
||||
|
||||
+65
-6
@@ -7434,6 +7434,8 @@ declare namespace ts {
|
||||
jsDocTypeExpression: JSDocTypeExpression;
|
||||
diagnostics: Diagnostic[];
|
||||
} | undefined;
|
||||
/** @internal */
|
||||
function isDeclarationFileName(fileName: string): boolean;
|
||||
interface PragmaContext {
|
||||
languageVersion: ScriptTarget;
|
||||
pragmas?: PragmaMap;
|
||||
@@ -8806,6 +8808,16 @@ declare namespace ts {
|
||||
extendedDiagnostics?: boolean;
|
||||
}
|
||||
function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter, compilerOptions?: SourceMapOptions): SourceMapWriter;
|
||||
interface SourceMapSection {
|
||||
version: 3;
|
||||
file: string;
|
||||
sourceRoot?: string;
|
||||
sources: string[];
|
||||
names?: string[];
|
||||
mappings: string;
|
||||
sourcesContent?: (string | null)[];
|
||||
sections?: undefined;
|
||||
}
|
||||
}
|
||||
declare namespace ts {
|
||||
interface CommentWriter {
|
||||
@@ -8969,10 +8981,14 @@ declare namespace ts {
|
||||
*/
|
||||
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
|
||||
function parseConfigHostFromCompilerHost(host: CompilerHost): ParseConfigFileHost;
|
||||
interface ResolveProjectReferencePathHost {
|
||||
fileExists(fileName: string): boolean;
|
||||
}
|
||||
/**
|
||||
* Returns the target config filename of a project reference
|
||||
* Returns the target config filename of a project reference.
|
||||
* Note: The file might not exist.
|
||||
*/
|
||||
function resolveProjectReferencePath(host: CompilerHost | UpToDateHost, ref: ProjectReference): ResolvedConfigFileName;
|
||||
function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName;
|
||||
/**
|
||||
* Returns a DiagnosticMessage if we won't include a resolved module due to its extension.
|
||||
* The DiagnosticMessage's parameters are the imported module name, and the filename it resolved to.
|
||||
@@ -10028,6 +10044,8 @@ declare namespace ts {
|
||||
getJsxClosingTagAtPosition(fileName: string, position: number): JsxClosingTagInfo | undefined;
|
||||
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined;
|
||||
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
|
||||
/** @internal */
|
||||
getSourceMapper(): SourceMapper;
|
||||
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray<CodeFixAction>;
|
||||
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
|
||||
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
|
||||
@@ -10898,6 +10916,8 @@ declare namespace ts {
|
||||
function getParentNodeInSpan(node: Node | undefined, file: SourceFile, span: TextSpan): Node | undefined;
|
||||
function findModifier(node: Node, kind: Modifier["kind"]): Modifier | undefined;
|
||||
function insertImport(changes: textChanges.ChangeTracker, sourceFile: SourceFile, importDecl: Statement): void;
|
||||
function textSpansEqual(a: TextSpan | undefined, b: TextSpan | undefined): boolean;
|
||||
function documentSpansEqual(a: DocumentSpan, b: DocumentSpan): boolean;
|
||||
}
|
||||
declare namespace ts {
|
||||
function isFirstDeclarationOfSymbolParameter(symbol: Symbol): boolean;
|
||||
@@ -11306,6 +11326,14 @@ declare namespace ts.SignatureHelp {
|
||||
}
|
||||
function getArgumentInfoForCompletions(node: Node, position: number, sourceFile: SourceFile): ArgumentInfoForCompletions | undefined;
|
||||
}
|
||||
declare namespace ts {
|
||||
interface SourceMapper {
|
||||
toLineColumnOffset(fileName: string, position: number): LineAndCharacter;
|
||||
tryGetOriginalLocation(info: sourcemaps.SourceMappableLocation): sourcemaps.SourceMappableLocation | undefined;
|
||||
clearCache(): void;
|
||||
}
|
||||
function getSourceMapper(getCanonicalFileName: GetCanonicalFileName, currentDirectory: string, log: (message: string) => void, host: LanguageServiceHost, getProgram: () => Program): SourceMapper;
|
||||
}
|
||||
declare namespace ts {
|
||||
function computeSuggestionDiagnostics(sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): DiagnosticWithLocation[];
|
||||
}
|
||||
@@ -12308,6 +12336,7 @@ declare namespace ts.server.protocol {
|
||||
DefinitionAndBoundSpanFull = "definitionAndBoundSpan-full",
|
||||
Implementation = "implementation",
|
||||
ImplementationFull = "implementation-full",
|
||||
EmitOutput = "emit-output",
|
||||
Exit = "exit",
|
||||
Format = "format",
|
||||
Formatonkey = "formatonkey",
|
||||
@@ -12630,6 +12659,17 @@ declare namespace ts.server.protocol {
|
||||
interface DefinitionRequest extends FileLocationRequest {
|
||||
command: CommandTypes.Definition;
|
||||
}
|
||||
interface DefinitionAndBoundSpanRequest extends FileLocationRequest {
|
||||
readonly command: CommandTypes.DefinitionAndBoundSpan;
|
||||
}
|
||||
interface DefinitionAndBoundSpanResponse extends Response {
|
||||
readonly body: DefinitionInfoAndBoundSpan;
|
||||
}
|
||||
interface EmitOutputRequest extends FileRequest {
|
||||
}
|
||||
interface EmitOutputResponse extends Response {
|
||||
readonly body: EmitOutput;
|
||||
}
|
||||
interface TypeDefinitionRequest extends FileLocationRequest {
|
||||
command: CommandTypes.TypeDefinition;
|
||||
}
|
||||
@@ -12728,6 +12768,13 @@ declare namespace ts.server.protocol {
|
||||
command: CommandTypes.Rename;
|
||||
arguments: RenameRequestArgs;
|
||||
}
|
||||
interface RenameFullRequest extends FileLocationRequest {
|
||||
readonly command: CommandTypes.RenameLocationsFull;
|
||||
readonly arguments: RenameRequestArgs;
|
||||
}
|
||||
interface RenameFullResponse extends Response {
|
||||
readonly body: ReadonlyArray<RenameLocation>;
|
||||
}
|
||||
interface RenameInfo {
|
||||
canRename: boolean;
|
||||
localizedErrorMessage?: string;
|
||||
@@ -13618,7 +13665,7 @@ declare namespace ts.server {
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
getNewLine(): string;
|
||||
getProjectVersion(): string;
|
||||
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined;
|
||||
getProjectReferences(): ReadonlyArray<ProjectReference>;
|
||||
getScriptFileNames(): string[];
|
||||
private getOrCreateScriptInfoAndAttachToProject;
|
||||
getScriptKind(fileName: string): ScriptKind;
|
||||
@@ -13650,6 +13697,7 @@ declare namespace ts.server {
|
||||
getGlobalProjectErrors(): ReadonlyArray<Diagnostic>;
|
||||
getAllProjectErrors(): ReadonlyArray<Diagnostic>;
|
||||
getLanguageService(ensureSynchronized?: boolean): LanguageService;
|
||||
getSourceMapper(): SourceMapper;
|
||||
private shouldEmitFile;
|
||||
getCompileOnSaveAffectedFileList(scriptInfo: ScriptInfo): string[];
|
||||
emitFile(scriptInfo: ScriptInfo, writeFile: (path: string, data: string, writeByteOrderMark?: boolean) => void): boolean;
|
||||
@@ -13732,7 +13780,7 @@ declare namespace ts.server {
|
||||
updateGraph(): boolean;
|
||||
getCachedDirectoryStructureHost(): CachedDirectoryStructureHost;
|
||||
getConfigFilePath(): NormalizedPath;
|
||||
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined;
|
||||
getProjectReferences(): ReadonlyArray<ProjectReference>;
|
||||
updateReferences(refs: ReadonlyArray<ProjectReference> | undefined): void;
|
||||
enablePlugins(): void;
|
||||
getGlobalProjectErrors(): ReadonlyArray<Diagnostic>;
|
||||
@@ -14008,8 +14056,8 @@ declare namespace ts.server {
|
||||
getSymlinkedProjects(info: ScriptInfo): MultiMap<Project> | undefined;
|
||||
private watchClosedScriptInfo;
|
||||
private stopWatchingScriptInfo;
|
||||
getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined, hostToQueryFileExistsOn: DirectoryStructureHost | undefined): ScriptInfo | undefined;
|
||||
getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, fileContent: string | undefined, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined): ScriptInfo | undefined;
|
||||
private getOrCreateScriptInfoNotOpenedByClientForNormalizedPath;
|
||||
private getOrCreateScriptInfoOpenedByClientForNormalizedPath;
|
||||
getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: {
|
||||
fileExists(path: string): boolean;
|
||||
}): ScriptInfo | undefined;
|
||||
@@ -14024,6 +14072,11 @@ declare namespace ts.server {
|
||||
private removeRootOfInferredProjectIfNowPartOfOtherProject;
|
||||
private ensureProjectForOpenFiles;
|
||||
openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: string): OpenConfiguredProjectResult;
|
||||
getProjectForFileWithoutOpening(fileName: NormalizedPath): {
|
||||
readonly scriptInfo: ScriptInfo;
|
||||
readonly projects: ReadonlyArray<Project>;
|
||||
} | undefined;
|
||||
fileExists(fileName: NormalizedPath): boolean;
|
||||
private findExternalProjectContainingOpenScriptInfo;
|
||||
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult;
|
||||
private telemetryOnOpenFile;
|
||||
@@ -14121,11 +14174,14 @@ declare namespace ts.server {
|
||||
private convertToDiagnosticsWithLinePosition;
|
||||
private getDiagnosticsWorker;
|
||||
private getDefinition;
|
||||
private mapDefinitionInfoLocations;
|
||||
private getDefinitionAndBoundSpan;
|
||||
private getEmitOutput;
|
||||
private mapDefinitionInfo;
|
||||
private static mapToOriginalLocation;
|
||||
private toFileSpan;
|
||||
private getTypeDefinition;
|
||||
private mapImplementationLocations;
|
||||
private getImplementation;
|
||||
private getOccurrences;
|
||||
private getSyntacticDiagnosticsSync;
|
||||
@@ -14140,6 +14196,8 @@ declare namespace ts.server {
|
||||
private getProjects;
|
||||
private getDefaultProject;
|
||||
private getRenameLocations;
|
||||
private static mapRenameInfo;
|
||||
private toSpanGroups;
|
||||
private getReferences;
|
||||
private openClientFile;
|
||||
private getPosition;
|
||||
@@ -14178,6 +14236,7 @@ declare namespace ts.server {
|
||||
private toLocationTextSpan;
|
||||
private getNavigationTree;
|
||||
private getNavigateToItems;
|
||||
private getFullNavigateToItems;
|
||||
private getSupportedCodeFixes;
|
||||
private isLocation;
|
||||
private extractPositionAndRange;
|
||||
|
||||
+6
-2
@@ -4139,10 +4139,14 @@ declare namespace ts {
|
||||
* @returns A 'Program' object.
|
||||
*/
|
||||
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
|
||||
interface ResolveProjectReferencePathHost {
|
||||
fileExists(fileName: string): boolean;
|
||||
}
|
||||
/**
|
||||
* Returns the target config filename of a project reference
|
||||
* Returns the target config filename of a project reference.
|
||||
* Note: The file might not exist.
|
||||
*/
|
||||
function resolveProjectReferencePath(host: CompilerHost | UpToDateHost, ref: ProjectReference): ResolvedConfigFileName;
|
||||
function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName;
|
||||
}
|
||||
declare namespace ts {
|
||||
interface EmitOutput {
|
||||
|
||||
@@ -4,6 +4,7 @@ Diagnostics:
|
||||
Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.
|
||||
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/a.js
|
||||
function foo2() { return 30; } // no error - should emit a.js
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
EmitSkipped: false
|
||||
FileName : ./dist/index.js
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var Foo = /** @class */ (function () {
|
||||
function Foo() {
|
||||
}
|
||||
Foo.prototype.methodName = function (propName) { };
|
||||
Foo.prototype.otherMethod = function () {
|
||||
if (Math.random() > 0.5) {
|
||||
return { x: 42 };
|
||||
}
|
||||
return { y: "yes" };
|
||||
};
|
||||
return Foo;
|
||||
}());
|
||||
exports.Foo = Foo;
|
||||
FileName : ./dist/index.d.ts.map
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../tests/cases/fourslash/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts
|
||||
export declare class Foo {
|
||||
member: string;
|
||||
methodName(propName: SomeType): void;
|
||||
otherMethod(): {
|
||||
x: number;
|
||||
y?: undefined;
|
||||
} | {
|
||||
y: string;
|
||||
x?: undefined;
|
||||
};
|
||||
}
|
||||
export interface SomeType {
|
||||
member: number;
|
||||
}
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -1,35 +0,0 @@
|
||||
EmitSkipped: false
|
||||
FileName : ./dist/index.js.map
|
||||
{"version":3,"file":"index.js","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":";;AAAA;IAAA;IASA,CAAC;IAPG,wBAAU,GAAV,UAAW,QAAkB,IAAS,CAAC;IACvC,yBAAW,GAAX;QACI,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,EAAE;YACrB,OAAO,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC;SAClB;QACD,OAAO,EAAC,CAAC,EAAE,KAAK,EAAC,CAAC;IACtB,CAAC;IACL,UAAC;AAAD,CAAC,AATD,IASC;AATY,kBAAG"}FileName : ./dist/index.js
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var Foo = /** @class */ (function () {
|
||||
function Foo() {
|
||||
}
|
||||
Foo.prototype.methodName = function (propName) { };
|
||||
Foo.prototype.otherMethod = function () {
|
||||
if (Math.random() > 0.5) {
|
||||
return { x: 42 };
|
||||
}
|
||||
return { y: "yes" };
|
||||
};
|
||||
return Foo;
|
||||
}());
|
||||
exports.Foo = Foo;
|
||||
//# sourceMappingURL=index.js.mapFileName : ./dist/index.d.ts.map
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts
|
||||
export declare class Foo {
|
||||
member: string;
|
||||
methodName(propName: SomeType): void;
|
||||
otherMethod(): {
|
||||
x: number;
|
||||
y?: undefined;
|
||||
} | {
|
||||
y: string;
|
||||
x?: undefined;
|
||||
};
|
||||
}
|
||||
export interface SomeType {
|
||||
member: number;
|
||||
}
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -1,34 +0,0 @@
|
||||
EmitSkipped: false
|
||||
FileName : ./dist/index.js
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var Foo = /** @class */ (function () {
|
||||
function Foo() {
|
||||
}
|
||||
Foo.prototype.methodName = function (propName) { };
|
||||
Foo.prototype.otherMethod = function () {
|
||||
if (Math.random() > 0.5) {
|
||||
return { x: 42 };
|
||||
}
|
||||
return { y: "yes" };
|
||||
};
|
||||
return Foo;
|
||||
}());
|
||||
exports.Foo = Foo;
|
||||
FileName : ./dist/index.d.ts.map
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"/tests/cases/fourslash/","sources":["index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts
|
||||
export declare class Foo {
|
||||
member: string;
|
||||
methodName(propName: SomeType): void;
|
||||
otherMethod(): {
|
||||
x: number;
|
||||
y?: undefined;
|
||||
} | {
|
||||
y: string;
|
||||
x?: undefined;
|
||||
};
|
||||
}
|
||||
export interface SomeType {
|
||||
member: number;
|
||||
}
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -1,34 +0,0 @@
|
||||
EmitSkipped: false
|
||||
FileName : ./dist/index.js
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var Foo = /** @class */ (function () {
|
||||
function Foo() {
|
||||
}
|
||||
Foo.prototype.methodName = function (propName) { };
|
||||
Foo.prototype.otherMethod = function () {
|
||||
if (Math.random() > 0.5) {
|
||||
return { x: 42 };
|
||||
}
|
||||
return { y: "yes" };
|
||||
};
|
||||
return Foo;
|
||||
}());
|
||||
exports.Foo = Foo;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90ZXN0cy9jYXNlcy9mb3Vyc2xhc2gvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTtJQUFBO0lBU0EsQ0FBQztJQVBHLHdCQUFVLEdBQVYsVUFBVyxRQUFrQixJQUFTLENBQUM7SUFDdkMseUJBQVcsR0FBWDtRQUNJLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRTtZQUNyQixPQUFPLEVBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBQyxDQUFDO1NBQ2xCO1FBQ0QsT0FBTyxFQUFDLENBQUMsRUFBRSxLQUFLLEVBQUMsQ0FBQztJQUN0QixDQUFDO0lBQ0wsVUFBQztBQUFELENBQUMsQUFURCxJQVNDO0FBVFksa0JBQUcifQ==FileName : ./dist/index.d.ts.map
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../tests/cases/fourslash/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts
|
||||
export declare class Foo {
|
||||
member: string;
|
||||
methodName(propName: SomeType): void;
|
||||
otherMethod(): {
|
||||
x: number;
|
||||
y?: undefined;
|
||||
} | {
|
||||
y: string;
|
||||
x?: undefined;
|
||||
};
|
||||
}
|
||||
export interface SomeType {
|
||||
member: number;
|
||||
}
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
EmitSkipped: false
|
||||
FileName : ./dist/index.js
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var Foo = /** @class */ (function () {
|
||||
function Foo() {
|
||||
}
|
||||
Foo.prototype.methodName = function (propName) { };
|
||||
Foo.prototype.otherMethod = function () {
|
||||
if (Math.random() > 0.5) {
|
||||
return { x: 42 };
|
||||
}
|
||||
return { y: "yes" };
|
||||
};
|
||||
return Foo;
|
||||
}());
|
||||
exports.Foo = Foo;
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90ZXN0cy9jYXNlcy9mb3Vyc2xhc2gvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQTtJQUFBO0lBU0EsQ0FBQztJQVBHLHdCQUFVLEdBQVYsVUFBVyxRQUFrQixJQUFTLENBQUM7SUFDdkMseUJBQVcsR0FBWDtRQUNJLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRTtZQUNyQixPQUFPLEVBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBQyxDQUFDO1NBQ2xCO1FBQ0QsT0FBTyxFQUFDLENBQUMsRUFBRSxLQUFLLEVBQUMsQ0FBQztJQUN0QixDQUFDO0lBQ0wsVUFBQztBQUFELENBQUMsQUFURCxJQVNDO0FBVFksa0JBQUciLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY2xhc3MgRm9vIHtcbiAgICBtZW1iZXI6IHN0cmluZztcbiAgICBtZXRob2ROYW1lKHByb3BOYW1lOiBTb21lVHlwZSk6IHZvaWQge31cbiAgICBvdGhlck1ldGhvZCgpIHtcbiAgICAgICAgaWYgKE1hdGgucmFuZG9tKCkgPiAwLjUpIHtcbiAgICAgICAgICAgIHJldHVybiB7eDogNDJ9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7eTogXCJ5ZXNcIn07XG4gICAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNvbWVUeXBlIHtcbiAgICBtZW1iZXI6IG51bWJlcjtcbn0iXX0=FileName : ./dist/index.d.ts.map
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../tests/cases/fourslash/index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}FileName : ./dist/index.d.ts
|
||||
export declare class Foo {
|
||||
member: string;
|
||||
methodName(propName: SomeType): void;
|
||||
otherMethod(): {
|
||||
x: number;
|
||||
y?: undefined;
|
||||
} | {
|
||||
y: string;
|
||||
x?: undefined;
|
||||
};
|
||||
}
|
||||
export interface SomeType {
|
||||
member: number;
|
||||
}
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/shims-pp/inputFile1.js
|
||||
var x = 5;
|
||||
var Bar = /** @class */ (function () {
|
||||
@@ -6,6 +7,7 @@ var Bar = /** @class */ (function () {
|
||||
}
|
||||
return Bar;
|
||||
}());
|
||||
|
||||
FileName : /tests/cases/fourslash/shims-pp/inputFile1.d.ts
|
||||
declare var x: number;
|
||||
declare class Bar {
|
||||
@@ -14,6 +16,7 @@ declare class Bar {
|
||||
}
|
||||
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/shims-pp/inputFile2.js
|
||||
var x1 = "hello world";
|
||||
var Foo = /** @class */ (function () {
|
||||
@@ -21,6 +24,7 @@ var Foo = /** @class */ (function () {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
|
||||
FileName : /tests/cases/fourslash/shims-pp/inputFile2.d.ts
|
||||
declare var x1: string;
|
||||
declare class Foo {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/shims/inputFile1.js
|
||||
var x = 5;
|
||||
var Bar = /** @class */ (function () {
|
||||
@@ -6,6 +7,7 @@ var Bar = /** @class */ (function () {
|
||||
}
|
||||
return Bar;
|
||||
}());
|
||||
|
||||
FileName : /tests/cases/fourslash/shims/inputFile1.d.ts
|
||||
declare var x: number;
|
||||
declare class Bar {
|
||||
@@ -14,6 +16,7 @@ declare class Bar {
|
||||
}
|
||||
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/shims/inputFile2.js
|
||||
var x1 = "hello world";
|
||||
var Foo = /** @class */ (function () {
|
||||
@@ -21,6 +24,7 @@ var Foo = /** @class */ (function () {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
|
||||
FileName : /tests/cases/fourslash/shims/inputFile2.d.ts
|
||||
declare var x1: string;
|
||||
declare class Foo {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile1.js
|
||||
var x = 5;
|
||||
var Bar = /** @class */ (function () {
|
||||
@@ -6,6 +7,7 @@ var Bar = /** @class */ (function () {
|
||||
}
|
||||
return Bar;
|
||||
}());
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile1.d.ts
|
||||
declare var x: number;
|
||||
declare class Bar {
|
||||
@@ -14,6 +16,7 @@ declare class Bar {
|
||||
}
|
||||
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile2.js
|
||||
var x1 = "hello world";
|
||||
var Foo = /** @class */ (function () {
|
||||
@@ -21,6 +24,7 @@ var Foo = /** @class */ (function () {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile2.d.ts
|
||||
declare var x1: string;
|
||||
declare class Foo {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : declSingleFile.js
|
||||
var x = 5;
|
||||
var Bar = /** @class */ (function () {
|
||||
@@ -12,6 +13,7 @@ var Foo = /** @class */ (function () {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
|
||||
FileName : declSingleFile.d.ts
|
||||
declare var x: number;
|
||||
declare class Bar {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : declSingleFile.js
|
||||
var x = 5;
|
||||
var Bar = /** @class */ (function () {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : declSingleFile.js
|
||||
var x = 5;
|
||||
var Bar = /** @class */ (function () {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : declSingleFile.js.map
|
||||
{"version":3,"file":"declSingleFile.js","sourceRoot":"","sources":["../inputFile.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : declSingleFile.js
|
||||
{"version":3,"file":"declSingleFile.js","sourceRoot":"","sources":["../inputFile.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}
|
||||
FileName : declSingleFile.js
|
||||
var x = 109;
|
||||
var foo = "hello world";
|
||||
var M = /** @class */ (function () {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile.js
|
||||
var x;
|
||||
var M = /** @class */ (function () {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile2.js
|
||||
var x;
|
||||
var Foo = /** @class */ (function () {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : out.js
|
||||
/// <reference path='my.d.ts' />
|
||||
var foo;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : outFile.js
|
||||
var x = 5;
|
||||
var Bar = /** @class */ (function () {
|
||||
@@ -12,6 +13,7 @@ var Foo = /** @class */ (function () {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
|
||||
FileName : outFile.d.ts
|
||||
declare var x: number;
|
||||
declare class Bar {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : outputDir/singleFile.js
|
||||
var x;
|
||||
var Bar = /** @class */ (function () {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : declSingleFile.js
|
||||
var x = 5;
|
||||
var Bar = /** @class */ (function () {
|
||||
@@ -12,6 +13,7 @@ var Foo = /** @class */ (function () {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
|
||||
FileName : declSingleFile.d.ts
|
||||
declare var x: number;
|
||||
declare class Bar {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile.js.map
|
||||
{"version":3,"file":"inputFile.js","sourceRoot":"","sources":["inputFile.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : /tests/cases/fourslash/inputFile.js
|
||||
{"version":3,"file":"inputFile.js","sourceRoot":"","sources":["inputFile.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}
|
||||
FileName : /tests/cases/fourslash/inputFile.js
|
||||
var x = 109;
|
||||
var foo = "hello world";
|
||||
var M = /** @class */ (function () {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : sample/outDir/inputFile1.js.map
|
||||
{"version":3,"file":"inputFile1.js","sourceRoot":"","sources":["../../tests/cases/fourslash/inputFile1.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : sample/outDir/inputFile1.js
|
||||
{"version":3,"file":"inputFile1.js","sourceRoot":"","sources":["../../tests/cases/fourslash/inputFile1.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}
|
||||
FileName : sample/outDir/inputFile1.js
|
||||
var x = 109;
|
||||
var foo = "hello world";
|
||||
var M = /** @class */ (function () {
|
||||
@@ -10,8 +12,10 @@ var M = /** @class */ (function () {
|
||||
}());
|
||||
//# sourceMappingURL=inputFile1.js.map
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : sample/outDir/inputFile2.js.map
|
||||
{"version":3,"file":"inputFile2.js","sourceRoot":"","sources":["../../tests/cases/fourslash/inputFile2.ts"],"names":[],"mappings":"AAAA,IAAI,KAAK,GAAG,aAAa,CAAC;AAC1B,IAAI,KAAK,KAAK,SAAS,EAAE;IACtB,IAAI,CAAC,GAAG,EAAE,CAAC;CACb"}FileName : sample/outDir/inputFile2.js
|
||||
{"version":3,"file":"inputFile2.js","sourceRoot":"","sources":["../../tests/cases/fourslash/inputFile2.ts"],"names":[],"mappings":"AAAA,IAAI,KAAK,GAAG,aAAa,CAAC;AAC1B,IAAI,KAAK,KAAK,SAAS,EAAE;IACtB,IAAI,CAAC,GAAG,EAAE,CAAC;CACb"}
|
||||
FileName : sample/outDir/inputFile2.js
|
||||
var intro = "hello world";
|
||||
if (intro !== undefined) {
|
||||
var k = 10;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile.js.map
|
||||
{"version":3,"file":"inputFile.js","sourceRoot":"sourceRootDir/","sources":["inputFile.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : /tests/cases/fourslash/inputFile.js
|
||||
{"version":3,"file":"inputFile.js","sourceRoot":"sourceRootDir/","sources":["inputFile.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}
|
||||
FileName : /tests/cases/fourslash/inputFile.js
|
||||
var x = 109;
|
||||
var foo = "hello world";
|
||||
var M = /** @class */ (function () {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile1.js.map
|
||||
{"version":3,"file":"inputFile1.js","sourceRoot":"sourceRootDir/","sources":["inputFile1.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : /tests/cases/fourslash/inputFile1.js
|
||||
{"version":3,"file":"inputFile1.js","sourceRoot":"sourceRootDir/","sources":["inputFile1.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,GAAG,CAAC;AACZ,IAAI,GAAG,GAAG,aAAa,CAAC;AACxB;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}
|
||||
FileName : /tests/cases/fourslash/inputFile1.js
|
||||
var x = 109;
|
||||
var foo = "hello world";
|
||||
var M = /** @class */ (function () {
|
||||
@@ -10,8 +12,10 @@ var M = /** @class */ (function () {
|
||||
}());
|
||||
//# sourceMappingURL=inputFile1.js.map
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile2.js.map
|
||||
{"version":3,"file":"inputFile2.js","sourceRoot":"sourceRootDir/","sources":["inputFile2.ts"],"names":[],"mappings":"AAAA,IAAI,GAAG,GAAG,wBAAwB,CAAC;AACnC;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}FileName : /tests/cases/fourslash/inputFile2.js
|
||||
{"version":3,"file":"inputFile2.js","sourceRoot":"sourceRootDir/","sources":["inputFile2.ts"],"names":[],"mappings":"AAAA,IAAI,GAAG,GAAG,wBAAwB,CAAC;AACnC;IAAA;IAGA,CAAC;IAAD,QAAC;AAAD,CAAC,AAHD,IAGC"}
|
||||
FileName : /tests/cases/fourslash/inputFile2.js
|
||||
var bar = "hello world Typescript";
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile1.js.map
|
||||
{"version":3,"file":"inputFile1.js","sourceRoot":"","sources":["inputFile1.ts"],"names":[],"mappings":"AAAA,kBAAkB;AACjB,IAAI,CAAC,GAAW,CAAC,CAAC;AAClB;IAAA;IAGA,CAAC;IAAD,UAAC;AAAD,CAAC,AAHD,IAGC"}FileName : /tests/cases/fourslash/inputFile1.js
|
||||
{"version":3,"file":"inputFile1.js","sourceRoot":"","sources":["inputFile1.ts"],"names":[],"mappings":"AAAA,kBAAkB;AACjB,IAAI,CAAC,GAAW,CAAC,CAAC;AAClB;IAAA;IAGA,CAAC;IAAD,UAAC;AAAD,CAAC,AAHD,IAGC"}
|
||||
FileName : /tests/cases/fourslash/inputFile1.js
|
||||
// regular ts file
|
||||
var t = 5;
|
||||
var Bar = /** @class */ (function () {
|
||||
@@ -8,7 +10,8 @@ var Bar = /** @class */ (function () {
|
||||
}
|
||||
return Bar;
|
||||
}());
|
||||
//# sourceMappingURL=inputFile1.js.mapFileName : /tests/cases/fourslash/inputFile1.d.ts
|
||||
//# sourceMappingURL=inputFile1.js.map
|
||||
FileName : /tests/cases/fourslash/inputFile1.d.ts
|
||||
declare var t: number;
|
||||
declare class Bar {
|
||||
x: string;
|
||||
@@ -16,11 +19,14 @@ declare class Bar {
|
||||
}
|
||||
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile2.jsx.map
|
||||
{"version":3,"file":"inputFile2.jsx","sourceRoot":"","sources":["inputFile2.tsx"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,QAAQ,CAAC;AACjB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,CAAC,CAAC,EAAG,CAAA"}FileName : /tests/cases/fourslash/inputFile2.jsx
|
||||
{"version":3,"file":"inputFile2.jsx","sourceRoot":"","sources":["inputFile2.tsx"],"names":[],"mappings":"AAAA,IAAI,CAAC,GAAG,QAAQ,CAAC;AACjB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,CAAC,CAAC,EAAG,CAAA"}
|
||||
FileName : /tests/cases/fourslash/inputFile2.jsx
|
||||
var y = "my div";
|
||||
var x = <div name={y}/>;
|
||||
//# sourceMappingURL=inputFile2.jsx.mapFileName : /tests/cases/fourslash/inputFile2.d.ts
|
||||
//# sourceMappingURL=inputFile2.jsx.map
|
||||
FileName : /tests/cases/fourslash/inputFile2.d.ts
|
||||
declare var y: string;
|
||||
declare var x: any;
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile1.js.map
|
||||
{"version":3,"file":"inputFile1.js","sourceRoot":"","sources":["inputFile1.ts"],"names":[],"mappings":"AAAA,kBAAkB;AACjB,IAAI,CAAC,GAAW,CAAC,CAAC;AAClB;IAAA;IAGA,CAAC;IAAD,UAAC;AAAD,CAAC,AAHD,IAGC"}FileName : /tests/cases/fourslash/inputFile1.js
|
||||
{"version":3,"file":"inputFile1.js","sourceRoot":"","sources":["inputFile1.ts"],"names":[],"mappings":"AAAA,kBAAkB;AACjB,IAAI,CAAC,GAAW,CAAC,CAAC;AAClB;IAAA;IAGA,CAAC;IAAD,UAAC;AAAD,CAAC,AAHD,IAGC"}
|
||||
FileName : /tests/cases/fourslash/inputFile1.js
|
||||
// regular ts file
|
||||
var t = 5;
|
||||
var Bar = /** @class */ (function () {
|
||||
@@ -8,7 +10,8 @@ var Bar = /** @class */ (function () {
|
||||
}
|
||||
return Bar;
|
||||
}());
|
||||
//# sourceMappingURL=inputFile1.js.mapFileName : /tests/cases/fourslash/inputFile1.d.ts
|
||||
//# sourceMappingURL=inputFile1.js.map
|
||||
FileName : /tests/cases/fourslash/inputFile1.d.ts
|
||||
declare var t: number;
|
||||
declare class Bar {
|
||||
x: string;
|
||||
@@ -16,11 +19,14 @@ declare class Bar {
|
||||
}
|
||||
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile2.js.map
|
||||
{"version":3,"file":"inputFile2.js","sourceRoot":"","sources":["inputFile2.tsx"],"names":[],"mappings":"AACA,IAAI,CAAC,GAAG,QAAQ,CAAC;AACjB,IAAI,CAAC,GAAG,6BAAK,IAAI,EAAG,CAAC,GAAI,CAAA"}FileName : /tests/cases/fourslash/inputFile2.js
|
||||
{"version":3,"file":"inputFile2.js","sourceRoot":"","sources":["inputFile2.tsx"],"names":[],"mappings":"AACA,IAAI,CAAC,GAAG,QAAQ,CAAC;AACjB,IAAI,CAAC,GAAG,6BAAK,IAAI,EAAG,CAAC,GAAI,CAAA"}
|
||||
FileName : /tests/cases/fourslash/inputFile2.js
|
||||
var y = "my div";
|
||||
var x = React.createElement("div", { name: y });
|
||||
//# sourceMappingURL=inputFile2.js.mapFileName : /tests/cases/fourslash/inputFile2.d.ts
|
||||
//# sourceMappingURL=inputFile2.js.map
|
||||
FileName : /tests/cases/fourslash/inputFile2.d.ts
|
||||
declare var React: any;
|
||||
declare var y: string;
|
||||
declare var x: any;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
EmitSkipped: false
|
||||
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile2.js
|
||||
var x1 = "hello world";
|
||||
var Foo = /** @class */ (function () {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
EmitSkipped: false
|
||||
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile2.js
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
@@ -12,6 +13,7 @@ var Foo = /** @class */ (function () {
|
||||
exports.Foo = Foo;
|
||||
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile3.js
|
||||
var x = "hello";
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : declSingle.js
|
||||
var x = "hello";
|
||||
var x1 = 1000;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile1.js
|
||||
// File contains early errors. All outputs should be skipped.
|
||||
var uninitialized_const_error;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile.js
|
||||
var M;
|
||||
(function (M) {
|
||||
@@ -9,6 +10,7 @@ var M;
|
||||
}());
|
||||
M.foo = new C();
|
||||
})(M || (M = {}));
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile.d.ts
|
||||
declare module M {
|
||||
class C {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile.js
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
"use strict";
|
||||
@@ -13,6 +14,7 @@ define(["require", "exports"], function (require, exports) {
|
||||
M.foo = new C();
|
||||
})(M = exports.M || (exports.M = {}));
|
||||
});
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile.d.ts
|
||||
class C {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile.js
|
||||
var x = "hello world";
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile.js
|
||||
var x = "hello world";
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile.d.ts
|
||||
declare var x: number;
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile1.js
|
||||
// File to emit, does not contain semantic errors
|
||||
// expected to be emitted correctelly regardless of the semantic errors in the other file
|
||||
var noErrors = true;
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile1.d.ts
|
||||
declare var noErrors: boolean;
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : out.js
|
||||
// File to emit, does not contain semantic errors, but --out is passed
|
||||
// expected to not generate declarations because of the semantic errors in the other file
|
||||
var noErrors = true;
|
||||
// File not emitted, and contains semantic errors
|
||||
var semanticError = "string";
|
||||
|
||||
FileName : out.d.ts
|
||||
declare var noErrors: boolean;
|
||||
declare var semanticError: boolean;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile1.js
|
||||
// File to emit, does not contain syntactic errors
|
||||
// expected to be emitted correctelly regardless of the syntactic errors in the other file
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : out.js
|
||||
// File to emit, does not contain syntactic errors, but --out is passed
|
||||
// expected to not generate outputs because of the syntactic errors in the other file.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
EmitSkipped: false
|
||||
|
||||
FileName : /tests/cases/fourslash/inputFile.js
|
||||
var x;
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
// @BaselineFile: declarationMapsGeneratedMapsEnableMapping_NoInline.baseline
|
||||
// @outDir: ./dist
|
||||
// @inlineSourceMap: true
|
||||
// @declaration: true
|
||||
// @declarationMap: true
|
||||
// @Filename: index.ts
|
||||
// @emitThisFile: true
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
// @Filename: mymodule.ts
|
||||
////import * as mod from "/dist/index";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
verify.baselineGetEmitOutput(/*insertResultIntoVfs*/ true);
|
||||
verify.goToDefinition("1", "2"); // getDefinitionAndBoundSpan
|
||||
verify.goToType("1", "2"); // getTypeDefinitionAtPosition
|
||||
goTo.marker("1");
|
||||
verify.goToDefinitionIs("2"); // getDefinitionAtPosition
|
||||
goTo.implementation(); // getImplementationAtPosition
|
||||
verify.caretAtMarker("2");
|
||||
@@ -1,35 +0,0 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
// @BaselineFile: declarationMapsGeneratedMapsEnableMapping_NoInlineSources.baseline
|
||||
// @outDir: ./dist
|
||||
// @inlineSourceMap: true
|
||||
// @inlineSources: true
|
||||
// @declaration: true
|
||||
// @declarationMap: true
|
||||
// @Filename: index.ts
|
||||
// @emitThisFile: true
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
// @Filename: mymodule.ts
|
||||
////import * as mod from "/dist/index";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
verify.baselineGetEmitOutput(/*insertResultIntoVfs*/ true);
|
||||
verify.goToDefinition("1", "2"); // getDefinitionAndBoundSpan
|
||||
verify.goToType("1", "2"); // getTypeDefinitionAtPosition
|
||||
goTo.marker("1");
|
||||
verify.goToDefinitionIs("2"); // getDefinitionAtPosition
|
||||
goTo.implementation(); // getImplementationAtPosition
|
||||
verify.caretAtMarker("2");
|
||||
@@ -1,33 +0,0 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
// @BaselineFile: declarationMapsGeneratedMapsEnableMapping.baseline
|
||||
// @outDir: ./dist
|
||||
// @declaration: true
|
||||
// @declarationMap: true
|
||||
// @Filename: index.ts
|
||||
// @emitThisFile: true
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
// @Filename: mymodule.ts
|
||||
////import * as mod from "/dist/index";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
verify.baselineGetEmitOutput(/*insertResultIntoVfs*/ true);
|
||||
verify.goToDefinition("1", "2"); // getDefinitionAndBoundSpan
|
||||
verify.goToType("1", "2"); // getTypeDefinitionAtPosition
|
||||
goTo.marker("1");
|
||||
verify.goToDefinitionIs("2"); // getDefinitionAtPosition
|
||||
goTo.implementation(); // getImplementationAtPosition
|
||||
verify.caretAtMarker("2");
|
||||
@@ -1,35 +0,0 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
// @BaselineFile: declarationMapsGeneratedMapsEnableMapping2.baseline
|
||||
// @outDir: ./dist
|
||||
// @sourceMap: true
|
||||
// @sourceRoot: /tests/cases/fourslash/
|
||||
// @declaration: true
|
||||
// @declarationMap: true
|
||||
// @Filename: index.ts
|
||||
// @emitThisFile: true
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
// @Filename: mymodule.ts
|
||||
////import * as mod from "/dist/index";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
verify.baselineGetEmitOutput(/*insertResultIntoVfs*/ true);
|
||||
verify.goToDefinition("1", "2"); // getDefinitionAndBoundSpan
|
||||
verify.goToType("1", "2"); // getTypeDefinitionAtPosition
|
||||
goTo.marker("1");
|
||||
verify.goToDefinitionIs("2"); // getDefinitionAtPosition
|
||||
goTo.implementation(); // getImplementationAtPosition
|
||||
verify.caretAtMarker("2");
|
||||
@@ -1,34 +0,0 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
// @BaselineFile: declarationMapsGeneratedMapsEnableMapping3.baseline
|
||||
// @outDir: ./dist
|
||||
// @sourceRoot: /tests/cases/fourslash/
|
||||
// @declaration: true
|
||||
// @declarationMap: true
|
||||
// @Filename: index.ts
|
||||
// @emitThisFile: true
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
// @Filename: mymodule.ts
|
||||
////import * as mod from "/dist/index";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
verify.baselineGetEmitOutput(/*insertResultIntoVfs*/ true);
|
||||
verify.goToDefinition("1", "2"); // getDefinitionAndBoundSpan
|
||||
verify.goToType("1", "2"); // getTypeDefinitionAtPosition
|
||||
goTo.marker("1");
|
||||
verify.goToDefinitionIs("2"); // getDefinitionAtPosition
|
||||
goTo.implementation(); // getImplementationAtPosition
|
||||
verify.caretAtMarker("2");
|
||||
@@ -271,6 +271,7 @@ declare namespace FourSlashInterface {
|
||||
baselineCurrentFileBreakpointLocations(): void;
|
||||
baselineCurrentFileNameOrDottedNameSpans(): void;
|
||||
baselineGetEmitOutput(insertResultsIntoVfs?: boolean): void;
|
||||
getEmitOutput(expectedOutputFiles: ReadonlyArray<string>): void;
|
||||
baselineQuickInfo(): void;
|
||||
nameOrDottedNameSpanTextIs(text: string): void;
|
||||
outliningSpansInCurrentFile(spans: Range[]): void;
|
||||
|
||||
+40
-40
@@ -1,40 +1,40 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
// @Filename: index.ts
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
// @Filename: indexdef.d.ts.map
|
||||
////{"version":3,"file":"indexdef.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;IACI,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}
|
||||
// @Filename: indexdef.d.ts
|
||||
////export declare class Foo {
|
||||
//// member: string;
|
||||
//// methodName(propName: SomeType): void;
|
||||
//// otherMethod(): {
|
||||
//// x: number;
|
||||
//// y?: undefined;
|
||||
//// } | {
|
||||
//// y: string;
|
||||
//// x?: undefined;
|
||||
//// };
|
||||
////}
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
//////# sourceMappingURL=indexdef.d.ts.map
|
||||
// @Filename: mymodule.ts
|
||||
////import * as mod from "./indexdef";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
verify.goToDefinition("1", "2");
|
||||
/// <reference path="../fourslash.ts" />
|
||||
// @Filename: index.ts
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
// @Filename: indexdef.d.ts.map
|
||||
////{"version":3,"file":"indexdef.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;IACI,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}
|
||||
// @Filename: indexdef.d.ts
|
||||
////export declare class Foo {
|
||||
//// member: string;
|
||||
//// methodName(propName: SomeType): void;
|
||||
//// otherMethod(): {
|
||||
//// x: number;
|
||||
//// y?: undefined;
|
||||
//// } | {
|
||||
//// y: string;
|
||||
//// x?: undefined;
|
||||
//// };
|
||||
////}
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
//////# sourceMappingURL=indexdef.d.ts.map
|
||||
// @Filename: mymodule.ts
|
||||
////import * as mod from "./indexdef";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
verify.goToDefinition("1", "2");
|
||||
@@ -0,0 +1,83 @@
|
||||
/// <reference path="../fourslash.ts" />
|
||||
|
||||
// @Filename: /tsconfig.json
|
||||
////{
|
||||
//// "compilerOptions": {
|
||||
//// "outDir": "./dist",
|
||||
//// "inlineSourceMap": true,
|
||||
//// "declaration": true,
|
||||
//// "declarationMap": true,
|
||||
//// "newLine": "lf",
|
||||
//// },
|
||||
//// "files": ["/index.ts"],
|
||||
////}
|
||||
|
||||
// @Filename: /index.ts
|
||||
// @emitThisFile: true
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
|
||||
// @Filename: /mymodule.ts
|
||||
////import * as mod from "/dist/index";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
// @Filename: /dist/index.js
|
||||
////"use strict";
|
||||
////exports.__esModule = true;
|
||||
////var Foo = /** @class */ (function () {
|
||||
//// function Foo() {
|
||||
//// }
|
||||
//// Foo.prototype.methodName = function (propName) { };
|
||||
//// Foo.prototype.otherMethod = function () {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return { x: 42 };
|
||||
//// }
|
||||
//// return { y: "yes" };
|
||||
//// };
|
||||
//// return Foo;
|
||||
////}());
|
||||
////exports.Foo = Foo;
|
||||
//////# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBO0lBQUE7SUFTQSxDQUFDO0lBUEcsd0JBQVUsR0FBVixVQUFXLFFBQWtCLElBQVMsQ0FBQztJQUN2Qyx5QkFBVyxHQUFYO1FBQ0ksSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsR0FBRyxFQUFFO1lBQ3JCLE9BQU8sRUFBQyxDQUFDLEVBQUUsRUFBRSxFQUFDLENBQUM7U0FDbEI7UUFDRCxPQUFPLEVBQUMsQ0FBQyxFQUFFLEtBQUssRUFBQyxDQUFDO0lBQ3RCLENBQUM7SUFDTCxVQUFDO0FBQUQsQ0FBQyxBQVRELElBU0M7QUFUWSxrQkFBRyJ9
|
||||
|
||||
// @Filename: /dist/index.d.ts.map
|
||||
////{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}
|
||||
|
||||
// @Filename: /dist/index.d.ts
|
||||
////export declare class Foo {
|
||||
//// member: string;
|
||||
//// methodName(propName: SomeType): void;
|
||||
//// otherMethod(): {
|
||||
//// x: number;
|
||||
//// y?: undefined;
|
||||
//// } | {
|
||||
//// y: string;
|
||||
//// x?: undefined;
|
||||
//// };
|
||||
////}
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
//////# sourceMappingURL=index.d.ts.map
|
||||
|
||||
goTo.file("/index.ts");
|
||||
verify.getEmitOutput(["/dist/index.js", "/dist/index.d.ts.map", "/dist/index.d.ts"]);
|
||||
|
||||
verify.goToDefinition("1", "2"); // getDefinitionAndBoundSpan
|
||||
verify.goToType("1", "2"); // getTypeDefinitionAtPosition
|
||||
goTo.marker("1");
|
||||
verify.goToDefinitionIs("2"); // getDefinitionAtPosition
|
||||
goTo.implementation(); // getImplementationAtPosition
|
||||
verify.caretAtMarker("2");
|
||||
@@ -0,0 +1,84 @@
|
||||
/// <reference path="../fourslash.ts" />
|
||||
|
||||
// @Filename: /tsconfig.json
|
||||
////{
|
||||
//// "compilerOptions": {
|
||||
//// "outDir": "./dist",
|
||||
//// "inlineSourceMap": true,
|
||||
//// "inlineSources": true,
|
||||
//// "declaration": true,
|
||||
//// "declarationMap": true,
|
||||
//// "newLine": "lf",
|
||||
//// },
|
||||
//// "files": ["/index.ts"],
|
||||
////}
|
||||
|
||||
// @Filename: /index.ts
|
||||
// @emitThisFile: true
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
|
||||
// @Filename: /mymodule.ts
|
||||
////import * as mod from "/dist/index";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
// @Filename: /dist/index.js
|
||||
////"use strict";
|
||||
////exports.__esModule = true;
|
||||
////var Foo = /** @class */ (function () {
|
||||
//// function Foo() {
|
||||
//// }
|
||||
//// Foo.prototype.methodName = function (propName) { };
|
||||
//// Foo.prototype.otherMethod = function () {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return { x: 42 };
|
||||
//// }
|
||||
//// return { y: "yes" };
|
||||
//// };
|
||||
//// return Foo;
|
||||
////}());
|
||||
////exports.Foo = Foo;
|
||||
//////# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBO0lBQUE7SUFTQSxDQUFDO0lBUEcsd0JBQVUsR0FBVixVQUFXLFFBQWtCLElBQVMsQ0FBQztJQUN2Qyx5QkFBVyxHQUFYO1FBQ0ksSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsR0FBRyxFQUFFO1lBQ3JCLE9BQU8sRUFBQyxDQUFDLEVBQUUsRUFBRSxFQUFDLENBQUM7U0FDbEI7UUFDRCxPQUFPLEVBQUMsQ0FBQyxFQUFFLEtBQUssRUFBQyxDQUFDO0lBQ3RCLENBQUM7SUFDTCxVQUFDO0FBQUQsQ0FBQyxBQVRELElBU0M7QUFUWSxrQkFBRyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjbGFzcyBGb28ge1xuICAgIG1lbWJlcjogc3RyaW5nO1xuICAgIG1ldGhvZE5hbWUocHJvcE5hbWU6IFNvbWVUeXBlKTogdm9pZCB7fVxuICAgIG90aGVyTWV0aG9kKCkge1xuICAgICAgICBpZiAoTWF0aC5yYW5kb20oKSA+IDAuNSkge1xuICAgICAgICAgICAgcmV0dXJuIHt4OiA0Mn07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHt5OiBcInllc1wifTtcbiAgICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU29tZVR5cGUge1xuICAgIG1lbWJlcjogbnVtYmVyO1xufSJdfQ==
|
||||
|
||||
// @Filename: /dist/index.d.ts.map
|
||||
////{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}
|
||||
|
||||
// @Filename: /dist/index.d.ts
|
||||
////export declare class Foo {
|
||||
//// member: string;
|
||||
//// methodName(propName: SomeType): void;
|
||||
//// otherMethod(): {
|
||||
//// x: number;
|
||||
//// y?: undefined;
|
||||
//// } | {
|
||||
//// y: string;
|
||||
//// x?: undefined;
|
||||
//// };
|
||||
////}
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
//////# sourceMappingURL=index.d.ts.map
|
||||
|
||||
goTo.file("/index.ts");
|
||||
verify.getEmitOutput(["/dist/index.js", "/dist/index.d.ts.map", "/dist/index.d.ts"]);
|
||||
|
||||
verify.goToDefinition("1", "2"); // getDefinitionAndBoundSpan
|
||||
verify.goToType("1", "2"); // getTypeDefinitionAtPosition
|
||||
goTo.marker("1");
|
||||
verify.goToDefinitionIs("2"); // getDefinitionAtPosition
|
||||
goTo.implementation(); // getImplementationAtPosition
|
||||
verify.caretAtMarker("2");
|
||||
@@ -0,0 +1,82 @@
|
||||
/// <reference path="../fourslash.ts" />
|
||||
|
||||
// @Filename: /tsconfig.json
|
||||
////{
|
||||
//// "compilerOptions": {
|
||||
//// "outDir": "./dist",
|
||||
//// "declaration": true,
|
||||
//// "declarationMap": true,
|
||||
//// "newLine": "lf",
|
||||
//// },
|
||||
//// "files": ["/index.ts"],
|
||||
////}
|
||||
|
||||
// @Filename: /index.ts
|
||||
// @emitThisFile: true
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
|
||||
// @Filename: /mymodule.ts
|
||||
////import * as mod from "/dist/index";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
// @Filename: /dist/index.js
|
||||
////"use strict";
|
||||
////exports.__esModule = true;
|
||||
////var Foo = /** @class */ (function () {
|
||||
//// function Foo() {
|
||||
//// }
|
||||
//// Foo.prototype.methodName = function (propName) { };
|
||||
//// Foo.prototype.otherMethod = function () {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return { x: 42 };
|
||||
//// }
|
||||
//// return { y: "yes" };
|
||||
//// };
|
||||
//// return Foo;
|
||||
////}());
|
||||
////exports.Foo = Foo;
|
||||
////
|
||||
|
||||
// @Filename: /dist/index.d.ts.map
|
||||
////{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}
|
||||
|
||||
// @Filename: /dist/index.d.ts
|
||||
////export declare class Foo {
|
||||
//// member: string;
|
||||
//// methodName(propName: SomeType): void;
|
||||
//// otherMethod(): {
|
||||
//// x: number;
|
||||
//// y?: undefined;
|
||||
//// } | {
|
||||
//// y: string;
|
||||
//// x?: undefined;
|
||||
//// };
|
||||
////}
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
//////# sourceMappingURL=index.d.ts.map
|
||||
|
||||
goTo.file("/index.ts");
|
||||
verify.getEmitOutput(["/dist/index.js", "/dist/index.d.ts.map", "/dist/index.d.ts"]);
|
||||
|
||||
verify.goToDefinition("1", "2"); // getDefinitionAndBoundSpan
|
||||
verify.goToType("1", "2"); // getTypeDefinitionAtPosition
|
||||
goTo.marker("1");
|
||||
verify.goToDefinitionIs("2"); // getDefinitionAtPosition
|
||||
goTo.implementation(); // getImplementationAtPosition
|
||||
verify.caretAtMarker("2");
|
||||
@@ -0,0 +1,87 @@
|
||||
/// <reference path="../fourslash.ts" />
|
||||
|
||||
// @Filename: /tsconfig.json
|
||||
////{
|
||||
//// "compilerOptions": {
|
||||
//// "outDir": "./dist",
|
||||
//// "sourceMap": true,
|
||||
//// "sourceRoot": "/",
|
||||
//// "declaration": true,
|
||||
//// "declarationMap": true,
|
||||
//// "newLine": "lf",
|
||||
//// },
|
||||
//// "files": ["/index.ts"],
|
||||
////}
|
||||
|
||||
// @Filename: /index.ts
|
||||
// @emitThisFile: true
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
|
||||
// @Filename: /mymodule.ts
|
||||
////import * as mod from "/dist/index";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
// @Filename: /dist/index.js.map
|
||||
////{"version":3,"file":"index.js","sourceRoot":"/","sources":["index.ts"],"names":[],"mappings":";;AAAA;IAAA;IASA,CAAC;IAPG,wBAAU,GAAV,UAAW,QAAkB,IAAS,CAAC;IACvC,yBAAW,GAAX;QACI,IAAI,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,EAAE;YACrB,OAAO,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC;SAClB;QACD,OAAO,EAAC,CAAC,EAAE,KAAK,EAAC,CAAC;IACtB,CAAC;IACL,UAAC;AAAD,CAAC,AATD,IASC;AATY,kBAAG"}
|
||||
|
||||
// @Filename: /dist/index.js
|
||||
////"use strict";
|
||||
////exports.__esModule = true;
|
||||
////var Foo = /** @class */ (function () {
|
||||
//// function Foo() {
|
||||
//// }
|
||||
//// Foo.prototype.methodName = function (propName) { };
|
||||
//// Foo.prototype.otherMethod = function () {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return { x: 42 };
|
||||
//// }
|
||||
//// return { y: "yes" };
|
||||
//// };
|
||||
//// return Foo;
|
||||
////}());
|
||||
////exports.Foo = Foo;
|
||||
//////# sourceMappingURL=index.js.map
|
||||
|
||||
// @Filename: /dist/index.d.ts.map
|
||||
////{"version":3,"file":"index.d.ts","sourceRoot":"/","sources":["index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}
|
||||
|
||||
// @Filename: /dist/index.d.ts
|
||||
////export declare class Foo {
|
||||
//// member: string;
|
||||
//// methodName(propName: SomeType): void;
|
||||
//// otherMethod(): {
|
||||
//// x: number;
|
||||
//// y?: undefined;
|
||||
//// } | {
|
||||
//// y: string;
|
||||
//// x?: undefined;
|
||||
//// };
|
||||
////}
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
//////# sourceMappingURL=index.d.ts.map
|
||||
|
||||
goTo.file("/index.ts");
|
||||
verify.getEmitOutput(["/dist/index.js.map", "/dist/index.js", "/dist/index.d.ts.map", "/dist/index.d.ts"]);
|
||||
|
||||
verify.goToDefinition("1", "2"); // getDefinitionAndBoundSpan
|
||||
verify.goToType("1", "2"); // getTypeDefinitionAtPosition
|
||||
goTo.marker("1");
|
||||
verify.goToDefinitionIs("2"); // getDefinitionAtPosition
|
||||
goTo.implementation(); // getImplementationAtPosition
|
||||
verify.caretAtMarker("2");
|
||||
@@ -0,0 +1,83 @@
|
||||
/// <reference path="../fourslash.ts" />
|
||||
|
||||
// @Filename: /tsconfig.json
|
||||
////{
|
||||
//// "compilerOptions": {
|
||||
//// "outDir": "./dist",
|
||||
//// "sourceRoot": "/",
|
||||
//// "declaration": true,
|
||||
//// "declarationMap": true,
|
||||
//// "newLine": "lf",
|
||||
//// },
|
||||
//// "files": ["/index.ts"],
|
||||
////}
|
||||
|
||||
// @Filename: /index.ts
|
||||
// @emitThisFile: true
|
||||
////export class Foo {
|
||||
//// member: string;
|
||||
//// /*2*/methodName(propName: SomeType): void {}
|
||||
//// otherMethod() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {x: 42};
|
||||
//// }
|
||||
//// return {y: "yes"};
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
|
||||
// @Filename: /mymodule.ts
|
||||
////import * as mod from "/dist/index";
|
||||
////const instance = new mod.Foo();
|
||||
////instance.[|/*1*/methodName|]({member: 12});
|
||||
|
||||
// @Filename: /dist/index.js
|
||||
////"use strict";
|
||||
////exports.__esModule = true;
|
||||
////var Foo = /** @class */ (function () {
|
||||
//// function Foo() {
|
||||
//// }
|
||||
//// Foo.prototype.methodName = function (propName) { };
|
||||
//// Foo.prototype.otherMethod = function () {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return { x: 42 };
|
||||
//// }
|
||||
//// return { y: "yes" };
|
||||
//// };
|
||||
//// return Foo;
|
||||
////}());
|
||||
////exports.Foo = Foo;
|
||||
////
|
||||
|
||||
// @Filename: /dist/index.d.ts.map
|
||||
////{"version":3,"file":"index.d.ts","sourceRoot":"/","sources":["index.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IACpC,WAAW;;;;;;;CAMd;AAED,MAAM,WAAW,QAAQ;IACrB,MAAM,EAAE,MAAM,CAAC;CAClB"}
|
||||
|
||||
// @Filename: /dist/index.d.ts
|
||||
////export declare class Foo {
|
||||
//// member: string;
|
||||
//// methodName(propName: SomeType): void;
|
||||
//// otherMethod(): {
|
||||
//// x: number;
|
||||
//// y?: undefined;
|
||||
//// } | {
|
||||
//// y: string;
|
||||
//// x?: undefined;
|
||||
//// };
|
||||
////}
|
||||
////export interface SomeType {
|
||||
//// member: number;
|
||||
////}
|
||||
//////# sourceMappingURL=index.d.ts.map
|
||||
|
||||
goTo.file("/index.ts");
|
||||
verify.getEmitOutput(["/dist/index.js", "/dist/index.d.ts.map", "/dist/index.d.ts"]);
|
||||
|
||||
verify.goToDefinition("1", "2"); // getDefinitionAndBoundSpan
|
||||
verify.goToType("1", "2"); // getTypeDefinitionAtPosition
|
||||
goTo.marker("1");
|
||||
verify.goToDefinitionIs("2"); // getDefinitionAtPosition
|
||||
goTo.implementation(); // getImplementationAtPosition
|
||||
verify.caretAtMarker("2");
|
||||
Reference in New Issue
Block a user