mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Fix issue with trailing directory separator not present if symlink wasnt detected by program (#55865)
This commit is contained in:
@@ -8802,9 +8802,15 @@ export function hasZeroOrOneAsteriskCharacter(str: string): boolean {
|
||||
|
||||
/** @internal */
|
||||
export interface SymlinkedDirectory {
|
||||
/** Matches the casing returned by `realpath`. Used to compute the `realpath` of children. */
|
||||
/**
|
||||
* Matches the casing returned by `realpath`. Used to compute the `realpath` of children.
|
||||
* Always has trailing directory separator
|
||||
*/
|
||||
real: string;
|
||||
/** toPath(real). Stored to avoid repeated recomputation. */
|
||||
/**
|
||||
* toPath(real). Stored to avoid repeated recomputation.
|
||||
* Always has trailing directory separator
|
||||
*/
|
||||
realPath: Path;
|
||||
}
|
||||
|
||||
@@ -8859,7 +8865,7 @@ export function createSymlinkCache(cwd: string, getCanonicalFileName: GetCanonic
|
||||
if (!containsIgnoredPath(symlinkPath)) {
|
||||
symlinkPath = ensureTrailingDirectorySeparator(symlinkPath);
|
||||
if (real !== false && !symlinkedDirectories?.has(symlinkPath)) {
|
||||
(symlinkedDirectoriesByRealpath ||= createMultiMap()).add(ensureTrailingDirectorySeparator(real.realPath), symlink);
|
||||
(symlinkedDirectoriesByRealpath ||= createMultiMap()).add(real.realPath, symlink);
|
||||
}
|
||||
(symlinkedDirectories || (symlinkedDirectories = new Map())).set(symlinkPath, real);
|
||||
}
|
||||
@@ -8882,7 +8888,10 @@ export function createSymlinkCache(cwd: string, getCanonicalFileName: GetCanonic
|
||||
if (commonResolved && commonOriginal) {
|
||||
cache.setSymlinkedDirectory(
|
||||
commonOriginal,
|
||||
{ real: commonResolved, realPath: toPath(commonResolved, cwd, getCanonicalFileName) },
|
||||
{
|
||||
real: ensureTrailingDirectorySeparator(commonResolved),
|
||||
realPath: ensureTrailingDirectorySeparator(toPath(commonResolved, cwd, getCanonicalFileName)),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
DirectoryWatcherCallback,
|
||||
DocumentPositionMapper,
|
||||
DocumentRegistry,
|
||||
ensureTrailingDirectorySeparator,
|
||||
enumerateInsertsAndDeletes,
|
||||
every,
|
||||
explainFiles,
|
||||
@@ -2520,8 +2521,8 @@ export class AutoImportProviderProject extends Project {
|
||||
const isSymlink = realPath && realPath !== hostProject.toPath(packageJson.packageDirectory);
|
||||
if (isSymlink) {
|
||||
symlinkCache.setSymlinkedDirectory(packageJson.packageDirectory, {
|
||||
real: real!,
|
||||
realPath,
|
||||
real: ensureTrailingDirectorySeparator(real!),
|
||||
realPath: ensureTrailingDirectorySeparator(realPath),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ export interface SymLink {
|
||||
|
||||
export type FileOrFolderOrSymLink = File | Folder | SymLink;
|
||||
export interface FileOrFolderOrSymLinkMap {
|
||||
[path: string]: string | Omit<FileOrFolderOrSymLink, "path">;
|
||||
[path: string]: string | Omit<File, "path"> | Omit<SymLink, "path"> | undefined;
|
||||
}
|
||||
export function isFile(fileOrFolderOrSymLink: FileOrFolderOrSymLink): fileOrFolderOrSymLink is File {
|
||||
return isString((fileOrFolderOrSymLink as File).content);
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
import * as Utils from "../../_namespaces/Utils";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
dedent,
|
||||
} from "../../_namespaces/Utils";
|
||||
import {
|
||||
libContent,
|
||||
} from "../helpers/contents";
|
||||
import {
|
||||
getFsConentsForNode10ResultAtTypesPackageJson,
|
||||
getFsContentsForNode10Result,
|
||||
getFsContentsForNode10ResultDts,
|
||||
getFsContentsForNode10ResultPackageJson,
|
||||
} from "../helpers/node10Result";
|
||||
import {
|
||||
solutionBuildWithBaseline,
|
||||
} from "../helpers/solutionBuilder";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createLoggerWithInMemoryLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolTextSpanFromSubstring,
|
||||
verifyGetErrRequest,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -38,14 +48,14 @@ describe("unittests:: tsserver:: moduleResolution", () => {
|
||||
};
|
||||
const fileA: File = {
|
||||
path: `/user/username/projects/myproject/src/fileA.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
import { foo } from "./fileB.mjs";
|
||||
foo();
|
||||
`,
|
||||
};
|
||||
const fileB: File = {
|
||||
path: `/user/username/projects/myproject/src/fileB.mts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
export function foo() {
|
||||
}
|
||||
`,
|
||||
@@ -195,4 +205,116 @@ describe("unittests:: tsserver:: moduleResolution", () => {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe("using referenced project", () => {
|
||||
it("not built", () => {
|
||||
verify();
|
||||
});
|
||||
it("built", () => {
|
||||
verify(/*built*/ true);
|
||||
});
|
||||
function verify(built?: boolean) {
|
||||
const indexContent = dedent`
|
||||
import { FOO } from "package-a";
|
||||
console.log(FOO);
|
||||
`;
|
||||
const host = createServerHost({
|
||||
"/home/src/projects/project/packages/package-a/package.json": getPackageJson("package-a"),
|
||||
"/home/src/projects/project/packages/package-a/tsconfig.json": getTsConfig(),
|
||||
"/home/src/projects/project/packages/package-a/src/index.ts": `export * from "./subfolder";`,
|
||||
"/home/src/projects/project/packages/package-a/src/subfolder/index.ts": `export const FOO = "bar";`,
|
||||
"/home/src/projects/project/packages/package-b/package.json": getPackageJson("package-b"),
|
||||
"/home/src/projects/project/packages/package-b/tsconfig.json": getTsConfig([{ path: "../package-a" }]),
|
||||
"/home/src/projects/project/packages/package-b/src/index.ts": indexContent,
|
||||
"/home/src/projects/project/node_modules/package-a": { symLink: "/home/src/projects/project/packages/package-a" },
|
||||
"/home/src/projects/project/node_modules/package-b": { symLink: "/home/src/projects/project/packages/package-b" },
|
||||
"/a/lib/lib.es2021.d.ts": libContent,
|
||||
}, { currentDirectory: "/home/src/projects/project" });
|
||||
if (built) {
|
||||
solutionBuildWithBaseline(host, ["packages/package-b"]);
|
||||
host.clearOutput();
|
||||
}
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host), canUseEvents: true });
|
||||
openFilesForSession(["/home/src/projects/project/packages/package-b/src/index.ts"], session);
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
files: ["/home/src/projects/project/packages/package-b/src/index.ts"],
|
||||
});
|
||||
const { end } = protocolTextSpanFromSubstring(indexContent, "package-a");
|
||||
session.executeCommandSeq<ts.server.protocol.UpdateOpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.UpdateOpen,
|
||||
arguments: {
|
||||
changedFiles: [{
|
||||
fileName: "/home/src/projects/project/packages/package-b/src/index.ts",
|
||||
textChanges: [{
|
||||
start: end,
|
||||
end,
|
||||
newText: "X",
|
||||
}],
|
||||
}],
|
||||
},
|
||||
});
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
files: ["/home/src/projects/project/packages/package-b/src/index.ts"],
|
||||
});
|
||||
session.executeCommandSeq<ts.server.protocol.UpdateOpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.UpdateOpen,
|
||||
arguments: {
|
||||
changedFiles: [{
|
||||
fileName: "/home/src/projects/project/packages/package-b/src/index.ts",
|
||||
textChanges: [{
|
||||
start: end,
|
||||
end: { ...end, offset: end.offset + 1 },
|
||||
newText: "",
|
||||
}],
|
||||
}],
|
||||
},
|
||||
});
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
files: ["/home/src/projects/project/packages/package-b/src/index.ts"],
|
||||
});
|
||||
baselineTsserverLogs("moduleResolution", `using referenced project${built ? " built" : ""}`, session);
|
||||
}
|
||||
function getPackageJson(packageName: string) {
|
||||
return JSON.stringify(
|
||||
{
|
||||
name: packageName,
|
||||
version: "1.0.0",
|
||||
type: "module",
|
||||
main: "build/index.js",
|
||||
exports: {
|
||||
".": "./build/index.js",
|
||||
"./package.json": "./package.json",
|
||||
"./*": ["./build/*/index.js", "./build/*.js"],
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
" ",
|
||||
);
|
||||
}
|
||||
|
||||
function getTsConfig(references?: object[]) {
|
||||
return JSON.stringify({
|
||||
compilerOptions: {
|
||||
allowSyntheticDefaultImports: true,
|
||||
baseUrl: "./",
|
||||
composite: true,
|
||||
declarationMap: true,
|
||||
esModuleInterop: true,
|
||||
lib: ["es2021"],
|
||||
module: "esnext",
|
||||
moduleResolution: "bundler",
|
||||
outDir: "build",
|
||||
rootDir: "./src",
|
||||
target: "ES2021",
|
||||
traceResolution: true,
|
||||
tsBuildInfoFile: "./build/tsconfig.tsbuildinfo",
|
||||
},
|
||||
include: ["./src/**/*.ts"],
|
||||
references,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user