Skip to content

Commit bb53936

Browse files
committed
Add tests that fail because of symlink to non common directory node_modules
1 parent a7b1717 commit bb53936

File tree

4 files changed

+150
-30
lines changed

4 files changed

+150
-30
lines changed

src/harness/fourslashImpl.ts

+39-25
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ namespace FourSlash {
2626

2727
files: FourSlashFile[];
2828

29+
symlinks: vfs.FileSet | undefined;
30+
2931
// A mapping from marker names to name/position pairs
3032
markerPositions: ts.Map<Marker>;
3133

@@ -342,6 +344,10 @@ namespace FourSlash {
342344
});
343345
}
344346

347+
if (testData.symlinks) {
348+
this.languageServiceAdapterHost.vfs.apply(testData.symlinks);
349+
}
350+
345351
this.formatCodeSettings = ts.testFormatSettings;
346352

347353
// Open the first file by default
@@ -3767,6 +3773,7 @@ namespace FourSlash {
37673773
const files: FourSlashFile[] = [];
37683774
// Global options
37693775
const globalOptions: { [s: string]: string; } = {};
3776+
let symlinks: vfs.FileSet | undefined;
37703777
// Marker positions
37713778

37723779
// Split up the input file by line
@@ -3815,32 +3822,38 @@ namespace FourSlash {
38153822
throw new Error("Three-slash line in the middle of four-slash region at line " + i);
38163823
}
38173824
else if (line.substr(0, 2) === "//") {
3818-
// Comment line, check for global/file @options and record them
3819-
const match = optionRegex.exec(line.substr(2));
3820-
if (match) {
3821-
const key = match[1].toLowerCase();
3822-
const value = match[2];
3823-
if (!ts.contains(fileMetadataNames, key)) {
3824-
// Check if the match is already existed in the global options
3825-
if (globalOptions[key] !== undefined) {
3826-
throw new Error(`Global option '${key}' already exists`);
3825+
const possiblySymlinks = Harness.TestCaseParser.parseSymlinkFromTest(line, symlinks);
3826+
if (possiblySymlinks) {
3827+
symlinks = possiblySymlinks;
3828+
}
3829+
else {
3830+
// Comment line, check for global/file @options and record them
3831+
const match = optionRegex.exec(line.substr(2));
3832+
if (match) {
3833+
const key = match[1].toLowerCase();
3834+
const value = match[2];
3835+
if (!ts.contains(fileMetadataNames, key)) {
3836+
// Check if the match is already existed in the global options
3837+
if (globalOptions[key] !== undefined) {
3838+
throw new Error(`Global option '${key}' already exists`);
3839+
}
3840+
globalOptions[key] = value;
38273841
}
3828-
globalOptions[key] = value;
3829-
}
3830-
else {
3831-
switch (key) {
3832-
case MetadataOptionNames.fileName:
3833-
// Found an @FileName directive, if this is not the first then create a new subfile
3834-
nextFile();
3835-
currentFileName = ts.isRootedDiskPath(value) ? value : basePath + "/" + value;
3836-
currentFileOptions[key] = value;
3837-
break;
3838-
case MetadataOptionNames.symlink:
3839-
currentFileSymlinks = ts.append(currentFileSymlinks, value);
3840-
break;
3841-
default:
3842-
// Add other fileMetadata flag
3843-
currentFileOptions[key] = value;
3842+
else {
3843+
switch (key) {
3844+
case MetadataOptionNames.fileName:
3845+
// Found an @FileName directive, if this is not the first then create a new subfile
3846+
nextFile();
3847+
currentFileName = ts.isRootedDiskPath(value) ? value : basePath + "/" + value;
3848+
currentFileOptions[key] = value;
3849+
break;
3850+
case MetadataOptionNames.symlink:
3851+
currentFileSymlinks = ts.append(currentFileSymlinks, value);
3852+
break;
3853+
default:
3854+
// Add other fileMetadata flag
3855+
currentFileOptions[key] = value;
3856+
}
38443857
}
38453858
}
38463859
}
@@ -3870,6 +3883,7 @@ namespace FourSlash {
38703883
markers,
38713884
globalOptions,
38723885
files,
3886+
symlinks,
38733887
ranges
38743888
};
38753889
}

src/harness/harnessIO.ts

+13-5
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,16 @@ namespace Harness {
11281128
const optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*([^\r\n]*)/gm; // multiple matches on multiple lines
11291129
const linkRegex = /^[\/]{2}\s*@link\s*:\s*([^\r\n]*)\s*->\s*([^\r\n]*)/gm; // multiple matches on multiple lines
11301130

1131+
export function parseSymlinkFromTest(line: string, symlinks: vfs.FileSet | undefined) {
1132+
const linkMetaData = linkRegex.exec(line);
1133+
linkRegex.lastIndex = 0;
1134+
if (!linkMetaData) return undefined;
1135+
1136+
if (!symlinks) symlinks = {};
1137+
symlinks[linkMetaData[2].trim()] = new vfs.Symlink(linkMetaData[1].trim());
1138+
return symlinks;
1139+
}
1140+
11311141
export function extractCompilerSettings(content: string): CompilerSettings {
11321142
const opts: CompilerSettings = {};
11331143

@@ -1163,11 +1173,9 @@ namespace Harness {
11631173

11641174
for (const line of lines) {
11651175
let testMetaData: RegExpExecArray | null;
1166-
const linkMetaData = linkRegex.exec(line);
1167-
linkRegex.lastIndex = 0;
1168-
if (linkMetaData) {
1169-
if (!symlinks) symlinks = {};
1170-
symlinks[linkMetaData[2].trim()] = new vfs.Symlink(linkMetaData[1].trim());
1176+
const possiblySymlinks = parseSymlinkFromTest(line, symlinks);
1177+
if (possiblySymlinks) {
1178+
symlinks = possiblySymlinks;
11711179
}
11721180
else if (testMetaData = optionRegex.exec(line)) {
11731181
// Comment line, check for global/file @options and record them
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/// <reference path="fourslash.ts" />
2+
// @experimentalDecorators: true
3+
4+
// @Filename: /project/libraries/dtos/tsconfig.json
5+
// { }
6+
7+
// @Filename: /project/libraries/dtos/src/book.entity.ts
8+
////@Entity()
9+
////export class BookEntity {
10+
//// id: number
11+
////}
12+
13+
// @Filename: /project/libraries/dtos/src/user.entity.ts
14+
////import { Entity } from "mikro-orm"
15+
////@Entity()
16+
////export class UserEntity {
17+
//// id: number
18+
////}
19+
20+
// @Filename: /project/common/temp/node_modules/.registry.npmjs.org/mikro-orm/[email protected]/node_modules/mikro-orm/package.json
21+
////{ "name": "mikro-orm", "version": "3.4.1", "typings": "dist/index.d.ts" }
22+
23+
// @Filename: /project/common/temp/node_modules/.registry.npmjs.org/mikro-orm/[email protected]/node_modules/mikro-orm/dist/index.d.ts
24+
////export * from "./decorators";
25+
26+
// @Filename: /project/common/temp/node_modules/.registry.npmjs.org/mikro-orm/[email protected]/node_modules/mikro-orm/dist/decorators/index.d.ts
27+
////export * from "./entity";
28+
29+
// @Filename: /project/common/temp/node_modules/.registry.npmjs.org/mikro-orm/[email protected]/node_modules/mikro-orm/dist/decorators/entity.d.ts
30+
////export declare function Entity(): Function;
31+
32+
// @link: /project/common/temp/node_modules/.registry.npmjs.org/mikro-orm/[email protected]/node_modules/mikro-orm -> /project/libraries/dtos/node_modules/mikro-orm
33+
34+
35+
goTo.file("/project/libraries/dtos/src/book.entity.ts");
36+
verify.importFixAtPosition([
37+
getImportFixContent("mikro-orm"),
38+
getImportFixContent("mikro-orm/dist/decorators"),
39+
getImportFixContent("mikro-orm/dist/decorators/entity"),
40+
]);
41+
42+
function getImportFixContent(from: string) {
43+
return `import { Entity } from "${from}";
44+
45+
@Entity()
46+
export class BookEntity {
47+
id: number
48+
}`;
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/// <reference path="fourslash.ts" />
2+
// @experimentalDecorators: true
3+
4+
// @Filename: /project/libraries/dtos/tsconfig.json
5+
// { }
6+
7+
// @Filename: /project/libraries/dtos/src/book.entity.ts
8+
////@Entity()
9+
////export class BookEntity {
10+
//// id: number
11+
////}
12+
13+
// @Filename: /project/libraries/dtos/src/user.entity.ts
14+
////import { Entity } from "mikro-orm"
15+
////@Entity()
16+
////export class UserEntity {
17+
//// id: number
18+
////}
19+
20+
// @Filename: /project/common/temp/node_modules/mikro-orm/package.json
21+
////{ "name": "mikro-orm", "version": "3.4.1", "typings": "dist/index.d.ts" }
22+
23+
// @Filename: /project/common/temp/node_modules/mikro-orm/dist/index.d.ts
24+
////export * from "./decorators";
25+
26+
// @Filename: /project/common/temp/node_modules/mikro-orm/dist/decorators/index.d.ts
27+
////export * from "./entity";
28+
29+
// @Filename: /project/common/temp/node_modules/mikro-orm/dist/decorators/entity.d.ts
30+
////export declare function Entity(): Function;
31+
32+
// @link: /project/common/temp/node_modules/mikro-orm -> /project/libraries/dtos/node_modules/mikro-orm
33+
34+
35+
goTo.file("/project/libraries/dtos/src/book.entity.ts");
36+
verify.importFixAtPosition([
37+
getImportFixContent("mikro-orm"),
38+
getImportFixContent("mikro-orm/dist/decorators"),
39+
getImportFixContent("mikro-orm/dist/decorators/entity"),
40+
]);
41+
42+
function getImportFixContent(from: string) {
43+
return `import { Entity } from "${from}";
44+
45+
@Entity()
46+
export class BookEntity {
47+
id: number
48+
}`;
49+
}

0 commit comments

Comments
 (0)