mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
When the imported module is through node_modules and symlink to folder that isnt node_modules (#37387)
* Add tests that fail because of symlink to non common directory node_modules * When the imported module is through node_modules and symlink to folder that isnt node_modules Most of the monorepo like scenarios are like this so looking at symlink to decide if file can be imported is essential Fixes #28689
This commit is contained in:
@@ -26,6 +26,8 @@ namespace FourSlash {
|
||||
|
||||
files: FourSlashFile[];
|
||||
|
||||
symlinks: vfs.FileSet | undefined;
|
||||
|
||||
// A mapping from marker names to name/position pairs
|
||||
markerPositions: ts.Map<Marker>;
|
||||
|
||||
@@ -342,6 +344,10 @@ namespace FourSlash {
|
||||
});
|
||||
}
|
||||
|
||||
if (testData.symlinks) {
|
||||
this.languageServiceAdapterHost.vfs.apply(testData.symlinks);
|
||||
}
|
||||
|
||||
this.formatCodeSettings = ts.testFormatSettings;
|
||||
|
||||
// Open the first file by default
|
||||
@@ -3767,6 +3773,7 @@ namespace FourSlash {
|
||||
const files: FourSlashFile[] = [];
|
||||
// Global options
|
||||
const globalOptions: { [s: string]: string; } = {};
|
||||
let symlinks: vfs.FileSet | undefined;
|
||||
// Marker positions
|
||||
|
||||
// Split up the input file by line
|
||||
@@ -3815,32 +3822,38 @@ namespace FourSlash {
|
||||
throw new Error("Three-slash line in the middle of four-slash region at line " + i);
|
||||
}
|
||||
else if (line.substr(0, 2) === "//") {
|
||||
// Comment line, check for global/file @options and record them
|
||||
const match = optionRegex.exec(line.substr(2));
|
||||
if (match) {
|
||||
const key = match[1].toLowerCase();
|
||||
const value = match[2];
|
||||
if (!ts.contains(fileMetadataNames, key)) {
|
||||
// Check if the match is already existed in the global options
|
||||
if (globalOptions[key] !== undefined) {
|
||||
throw new Error(`Global option '${key}' already exists`);
|
||||
const possiblySymlinks = Harness.TestCaseParser.parseSymlinkFromTest(line, symlinks);
|
||||
if (possiblySymlinks) {
|
||||
symlinks = possiblySymlinks;
|
||||
}
|
||||
else {
|
||||
// Comment line, check for global/file @options and record them
|
||||
const match = optionRegex.exec(line.substr(2));
|
||||
if (match) {
|
||||
const key = match[1].toLowerCase();
|
||||
const value = match[2];
|
||||
if (!ts.contains(fileMetadataNames, key)) {
|
||||
// Check if the match is already existed in the global options
|
||||
if (globalOptions[key] !== undefined) {
|
||||
throw new Error(`Global option '${key}' already exists`);
|
||||
}
|
||||
globalOptions[key] = value;
|
||||
}
|
||||
globalOptions[key] = value;
|
||||
}
|
||||
else {
|
||||
switch (key) {
|
||||
case MetadataOptionNames.fileName:
|
||||
// Found an @FileName directive, if this is not the first then create a new subfile
|
||||
nextFile();
|
||||
currentFileName = ts.isRootedDiskPath(value) ? value : basePath + "/" + value;
|
||||
currentFileOptions[key] = value;
|
||||
break;
|
||||
case MetadataOptionNames.symlink:
|
||||
currentFileSymlinks = ts.append(currentFileSymlinks, value);
|
||||
break;
|
||||
default:
|
||||
// Add other fileMetadata flag
|
||||
currentFileOptions[key] = value;
|
||||
else {
|
||||
switch (key) {
|
||||
case MetadataOptionNames.fileName:
|
||||
// Found an @FileName directive, if this is not the first then create a new subfile
|
||||
nextFile();
|
||||
currentFileName = ts.isRootedDiskPath(value) ? value : basePath + "/" + value;
|
||||
currentFileOptions[key] = value;
|
||||
break;
|
||||
case MetadataOptionNames.symlink:
|
||||
currentFileSymlinks = ts.append(currentFileSymlinks, value);
|
||||
break;
|
||||
default:
|
||||
// Add other fileMetadata flag
|
||||
currentFileOptions[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3870,6 +3883,7 @@ namespace FourSlash {
|
||||
markers,
|
||||
globalOptions,
|
||||
files,
|
||||
symlinks,
|
||||
ranges
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1128,6 +1128,16 @@ namespace Harness {
|
||||
const optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*([^\r\n]*)/gm; // multiple matches on multiple lines
|
||||
const linkRegex = /^[\/]{2}\s*@link\s*:\s*([^\r\n]*)\s*->\s*([^\r\n]*)/gm; // multiple matches on multiple lines
|
||||
|
||||
export function parseSymlinkFromTest(line: string, symlinks: vfs.FileSet | undefined) {
|
||||
const linkMetaData = linkRegex.exec(line);
|
||||
linkRegex.lastIndex = 0;
|
||||
if (!linkMetaData) return undefined;
|
||||
|
||||
if (!symlinks) symlinks = {};
|
||||
symlinks[linkMetaData[2].trim()] = new vfs.Symlink(linkMetaData[1].trim());
|
||||
return symlinks;
|
||||
}
|
||||
|
||||
export function extractCompilerSettings(content: string): CompilerSettings {
|
||||
const opts: CompilerSettings = {};
|
||||
|
||||
@@ -1163,11 +1173,9 @@ namespace Harness {
|
||||
|
||||
for (const line of lines) {
|
||||
let testMetaData: RegExpExecArray | null;
|
||||
const linkMetaData = linkRegex.exec(line);
|
||||
linkRegex.lastIndex = 0;
|
||||
if (linkMetaData) {
|
||||
if (!symlinks) symlinks = {};
|
||||
symlinks[linkMetaData[2].trim()] = new vfs.Symlink(linkMetaData[1].trim());
|
||||
const possiblySymlinks = parseSymlinkFromTest(line, symlinks);
|
||||
if (possiblySymlinks) {
|
||||
symlinks = possiblySymlinks;
|
||||
}
|
||||
else if (testMetaData = optionRegex.exec(line)) {
|
||||
// Comment line, check for global/file @options and record them
|
||||
|
||||
Reference in New Issue
Block a user