Skip to content

Commit 6f79e66

Browse files
authored
Parse @link directive in compiler tests and add symlinks (microsoft#421)
1 parent b3ee9c8 commit 6f79e66

File tree

30 files changed

+492
-250
lines changed

30 files changed

+492
-250
lines changed

internal/testutil/harnessutil/harnessutil.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func CompileFiles(
8282
testConfig TestConfiguration,
8383
tsconfigOptions *core.CompilerOptions,
8484
currentDirectory string,
85-
symlinks any,
85+
symlinks map[string]string,
8686
) *CompilationResult {
8787
var compilerOptions core.CompilerOptions
8888
if tsconfigOptions != nil {
@@ -129,16 +129,8 @@ func CompileFiles(
129129
// }
130130

131131
// !!!
132-
// docs := append(inputFiles, otherFiles...) // !!! Convert to `TextDocument`
133-
// const fs = vfs.createFromFileSystem(IO, !useCaseSensitiveFileNames, { documents: docs, cwd: currentDirectory });
134-
// if (symlinks) {
135-
// fs.apply(symlinks);
136-
// }
137-
138132
// ts.assign(options, ts.convertToOptionsWithAbsolutePaths(options, path => ts.getNormalizedAbsolutePath(path, currentDirectory)));
139133

140-
// !!! Port vfs usage closer to original
141-
142134
// Create fake FS for testing
143135
testfs := map[string]any{}
144136
for _, file := range inputFiles {
@@ -153,6 +145,11 @@ func CompileFiles(
153145
Data: []byte(file.Content),
154146
}
155147
}
148+
for src, target := range symlinks {
149+
srcFileName := tspath.GetNormalizedAbsolutePath(src, currentDirectory)
150+
targetFileName := tspath.GetNormalizedAbsolutePath(target, currentDirectory)
151+
testfs[srcFileName] = vfstest.Symlink(targetFileName)
152+
}
156153

157154
fs := vfstest.FromMap(testfs, harnessOptions.UseCaseSensitiveFileNames)
158155
fs = bundled.WrapFS(fs)

internal/testutil/runner/test_case_parser.go

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@ type testCaseContent struct {
3333
testUnitData []*testUnit
3434
tsConfig *tsoptions.ParsedCommandLine
3535
tsConfigFileUnitData *testUnit
36-
symlinks any // !!!
36+
symlinks map[string]string
3737
}
3838

3939
// Regex for parsing options in the format "@Alpha: Value of any sort"
40-
var optionRegex = regexp.MustCompile(`(?m)^\/{2}\s*@(\w+)\s*:\s*([^\r\n]*)`) // multiple matches on multiple lines
40+
var optionRegex = regexp.MustCompile(`(?m)^\/{2}\s*@(\w+)\s*:\s*([^\r\n]*)`)
41+
42+
// Regex for parsing @link option
43+
var linkRegex = regexp.MustCompile(`(?m)^\/{2}\s*@link\s*:\s*([^\r\n]*)\s*->\s*([^\r\n]*)`)
4144

4245
// Given a test file containing // @FileName directives,
4346
// return an array of named units of code to be added to an existing compiler instance.
@@ -51,15 +54,13 @@ func makeUnitsFromTest(code string, fileName string) testCaseContent {
5154
var currentFileContent strings.Builder
5255
var currentFileName string
5356
currentDirectory := srcFolder
54-
// var symlinks any
57+
symlinks := make(map[string]string)
5558

5659
for _, line := range lines {
57-
// !!!
58-
// const possiblySymlinks = parseSymlinkFromTest(line, symlinks, vfs.srcFolder);
59-
// if (possiblySymlinks) {
60-
// symlinks = possiblySymlinks;
61-
// }
62-
// !!! should be else if
60+
ok := parseSymlinkFromTest(line, symlinks)
61+
if ok {
62+
continue
63+
}
6364
if testMetaData := optionRegex.FindStringSubmatch(line); testMetaData != nil {
6465
// Comment line, check for global/file @options and record them
6566
metaDataName := strings.ToLower(testMetaData[1])
@@ -156,6 +157,7 @@ func makeUnitsFromTest(code string, fileName string) testCaseContent {
156157
testUnitData: testUnits,
157158
tsConfig: tsConfig,
158159
tsConfigFileUnitData: tsConfigFileUnitData,
160+
symlinks: symlinks,
159161
}
160162
}
161163

@@ -168,3 +170,13 @@ func extractCompilerSettings(content string) rawCompilerSettings {
168170

169171
return opts
170172
}
173+
174+
func parseSymlinkFromTest(line string, symlinks map[string]string) bool {
175+
linkMetaData := linkRegex.FindStringSubmatch(line)
176+
if len(linkMetaData) == 0 {
177+
return false
178+
}
179+
180+
symlinks[strings.TrimSpace(linkMetaData[2])] = strings.TrimSpace(linkMetaData[1])
181+
return true
182+
}

internal/testutil/runner/test_case_parser_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function bar() { return "b"; }`,
3333
testUnitData: []*testUnit{testUnit1, testUnit2},
3434
tsConfig: nil,
3535
tsConfigFileUnitData: nil,
36-
symlinks: nil,
36+
symlinks: make(map[string]string),
3737
}
3838
assert.DeepEqual(
3939
t,
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//// [tests/cases/compiler/symbolLinkDeclarationEmitModuleNamesRootDir.ts] ////
2+
3+
=== /monorepo/core/src/application.ts ===
4+
import { Constructor } from "@loopback/context";
5+
>Constructor : Symbol(Constructor, Decl(application.ts, 0, 8))
6+
7+
export type ControllerClass = Constructor<any>;
8+
>ControllerClass : Symbol(ControllerClass, Decl(application.ts, 0, 48))
9+
>Constructor : Symbol(Constructor, Decl(application.ts, 0, 8))
10+
11+
=== /monorepo/core/src/usage.ts ===
12+
import { ControllerClass } from './application';
13+
>ControllerClass : Symbol(ControllerClass, Decl(usage.ts, 0, 8))
14+
15+
import { BindingKey } from '@loopback/context';
16+
>BindingKey : Symbol(BindingKey, Decl(usage.ts, 1, 8))
17+
18+
export const CONTROLLER_CLASS = BindingKey.create<ControllerClass>(null as any); // line in question
19+
>CONTROLLER_CLASS : Symbol(CONTROLLER_CLASS, Decl(usage.ts, 3, 12))
20+
>BindingKey.create : Symbol(create, Decl(bindingkey.d.ts, 2, 21))
21+
>BindingKey : Symbol(BindingKey, Decl(usage.ts, 1, 8))
22+
>create : Symbol(create, Decl(bindingkey.d.ts, 2, 21))
23+
>ControllerClass : Symbol(ControllerClass, Decl(usage.ts, 0, 8))
24+
25+
=== /monorepo/context/src/value-promise.d.ts ===
26+
export type Constructor<T> = (...args: any[]) => T;
27+
>Constructor : Symbol(Constructor, Decl(value-promise.d.ts, 0, 0))
28+
>T : Symbol(T, Decl(value-promise.d.ts, 0, 24))
29+
>args : Symbol(args, Decl(value-promise.d.ts, 0, 30))
30+
>T : Symbol(T, Decl(value-promise.d.ts, 0, 24))
31+
32+
=== /monorepo/context/src/bindingkey.d.ts ===
33+
import { Constructor } from "./value-promise"
34+
>Constructor : Symbol(Constructor, Decl(bindingkey.d.ts, 0, 8))
35+
36+
export declare class BindingKey<T> {
37+
>BindingKey : Symbol(BindingKey, Decl(bindingkey.d.ts, 0, 45))
38+
>T : Symbol(T, Decl(bindingkey.d.ts, 1, 32))
39+
40+
readonly __type: T;
41+
>__type : Symbol(__type, Decl(bindingkey.d.ts, 1, 36))
42+
>T : Symbol(T, Decl(bindingkey.d.ts, 1, 32))
43+
44+
static create<T extends Constructor<any>>(ctor: T): BindingKey<T>;
45+
>create : Symbol(create, Decl(bindingkey.d.ts, 2, 21))
46+
>T : Symbol(T, Decl(bindingkey.d.ts, 3, 16))
47+
>Constructor : Symbol(Constructor, Decl(bindingkey.d.ts, 0, 8))
48+
>ctor : Symbol(ctor, Decl(bindingkey.d.ts, 3, 44))
49+
>T : Symbol(T, Decl(bindingkey.d.ts, 3, 16))
50+
>BindingKey : Symbol(BindingKey, Decl(bindingkey.d.ts, 0, 45))
51+
>T : Symbol(T, Decl(bindingkey.d.ts, 3, 16))
52+
}
53+
54+
=== /monorepo/context/index.d.ts ===
55+
56+
export * from "./src/value-promise";
57+
export * from "./src/bindingkey";
58+
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//// [tests/cases/compiler/symbolLinkDeclarationEmitModuleNamesRootDir.ts] ////
2+
3+
=== /monorepo/core/src/application.ts ===
4+
import { Constructor } from "@loopback/context";
5+
>Constructor : error
6+
7+
export type ControllerClass = Constructor<any>;
8+
>ControllerClass : ControllerClass
9+
10+
=== /monorepo/core/src/usage.ts ===
11+
import { ControllerClass } from './application';
12+
>ControllerClass : error
13+
14+
import { BindingKey } from '@loopback/context';
15+
>BindingKey : { new<T>(): BindingKey<T>, create: <T>(ctor: T) => BindingKey<T>, prototype: BindingKey<any> }
16+
17+
export const CONTROLLER_CLASS = BindingKey.create<ControllerClass>(null as any); // line in question
18+
>CONTROLLER_CLASS : BindingKey<ControllerClass>
19+
>BindingKey.create<ControllerClass>(null as any) : BindingKey<ControllerClass>
20+
>BindingKey.create : <T>(ctor: T) => BindingKey<T>
21+
>BindingKey : { new<T>(): BindingKey<T>, create: <T>(ctor: T) => BindingKey<T>, prototype: BindingKey<any> }
22+
>create : <T>(ctor: T) => BindingKey<T>
23+
>null as any : any
24+
25+
=== /monorepo/context/src/value-promise.d.ts ===
26+
export type Constructor<T> = (...args: any[]) => T;
27+
>Constructor : Constructor<T>
28+
>T : T
29+
>args : any[]
30+
31+
=== /monorepo/context/src/bindingkey.d.ts ===
32+
import { Constructor } from "./value-promise"
33+
>Constructor : error
34+
35+
export declare class BindingKey<T> {
36+
>BindingKey : BindingKey<T>
37+
>T : T
38+
39+
readonly __type: T;
40+
>__type : T
41+
42+
static create<T extends Constructor<any>>(ctor: T): BindingKey<T>;
43+
>create : <T>(ctor: T) => BindingKey<T>
44+
>T : T
45+
>ctor : T
46+
}
47+
48+
=== /monorepo/context/index.d.ts ===
49+
50+
export * from "./src/value-promise";
51+
export * from "./src/bindingkey";
52+

testdata/baselines/reference/submodule/compiler/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.symbols

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
=== /a/index.ts ===
44

55
export * from "./src/"
6+
=== /b/index.ts ===
7+
8+
export * from "./src/"
9+
=== /b/src/index.ts ===
10+
export class B {}
11+
>B : Symbol(B, Decl(index.ts, 0, 0))
12+
613
=== /a/src/index.ts ===
714
import { B } from "b";
815
>B : Symbol(B, Decl(index.ts, 0, 8))

testdata/baselines/reference/submodule/compiler/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.symbols.diff

Lines changed: 0 additions & 16 deletions
This file was deleted.

testdata/baselines/reference/submodule/compiler/declarationEmitForGlobalishSpecifierSymlink2.symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@ export const a = getA();
2828
=== /p2/index.d.ts ===
2929
export const a: import("typescript-fsa").A;
3030
>a : Symbol(a, Decl(index.d.ts, 0, 12))
31+
>A : Symbol(A, Decl(impl.d.ts, 0, 26))
3132

3233

testdata/baselines/reference/submodule/compiler/declarationEmitForGlobalishSpecifierSymlink2.symbols.diff

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,3 @@
99
}
1010
=== /cache/typescript-fsa/index.d.ts ===
1111

12-
@@= skipped -19, +19 lines =@@
13-
=== /p2/index.d.ts ===
14-
export const a: import("typescript-fsa").A;
15-
>a : Symbol(a, Decl(index.d.ts, 0, 12))
16-
->A : Symbol(A, Decl(impl.d.ts, 0, 26))
17-
18-

testdata/baselines/reference/submodule/compiler/declarationEmitReexportedSymlinkReference.symbols

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,61 @@ import {MetadataAccessor} from "@raymondfeng/pkg2";
99

1010
export const ADMIN = MetadataAccessor.create<boolean>('1');
1111
>ADMIN : Symbol(ADMIN, Decl(keys.ts, 2, 12))
12+
>MetadataAccessor.create : Symbol(create, Decl(types.d.ts, 10, 23))
1213
>MetadataAccessor : Symbol(MetadataAccessor, Decl(keys.ts, 0, 8))
14+
>create : Symbol(create, Decl(types.d.ts, 10, 23))
1315

16+
=== monorepo/pkg1/dist/index.d.ts ===
17+
18+
export * from './types';
19+
=== monorepo/pkg1/dist/types.d.ts ===
20+
export declare type A = {
21+
>A : Symbol(A, Decl(types.d.ts, 0, 0))
22+
23+
id: string;
24+
>id : Symbol(id, Decl(types.d.ts, 0, 25))
25+
26+
};
27+
export declare type B = {
28+
>B : Symbol(B, Decl(types.d.ts, 2, 2))
29+
30+
id: number;
31+
>id : Symbol(id, Decl(types.d.ts, 3, 25))
32+
33+
};
34+
export declare type IdType = A | B;
35+
>IdType : Symbol(IdType, Decl(types.d.ts, 5, 2))
36+
>A : Symbol(A, Decl(types.d.ts, 0, 0))
37+
>B : Symbol(B, Decl(types.d.ts, 2, 2))
38+
39+
export declare class MetadataAccessor<T, D extends IdType = IdType> {
40+
>MetadataAccessor : Symbol(MetadataAccessor, Decl(types.d.ts, 6, 35))
41+
>T : Symbol(T, Decl(types.d.ts, 7, 38))
42+
>D : Symbol(D, Decl(types.d.ts, 7, 40))
43+
>IdType : Symbol(IdType, Decl(types.d.ts, 5, 2))
44+
>IdType : Symbol(IdType, Decl(types.d.ts, 5, 2))
45+
46+
readonly key: string;
47+
>key : Symbol(key, Decl(types.d.ts, 7, 69))
48+
49+
private constructor();
50+
toString(): string;
51+
>toString : Symbol(toString, Decl(types.d.ts, 9, 26))
52+
53+
static create<T, D extends IdType = IdType>(key: string): MetadataAccessor<T, D>;
54+
>create : Symbol(create, Decl(types.d.ts, 10, 23))
55+
>T : Symbol(T, Decl(types.d.ts, 11, 18))
56+
>D : Symbol(D, Decl(types.d.ts, 11, 20))
57+
>IdType : Symbol(IdType, Decl(types.d.ts, 5, 2))
58+
>IdType : Symbol(IdType, Decl(types.d.ts, 5, 2))
59+
>key : Symbol(key, Decl(types.d.ts, 11, 48))
60+
>MetadataAccessor : Symbol(MetadataAccessor, Decl(types.d.ts, 6, 35))
61+
>T : Symbol(T, Decl(types.d.ts, 11, 18))
62+
>D : Symbol(D, Decl(types.d.ts, 11, 20))
63+
}
64+
=== monorepo/pkg2/dist/index.d.ts ===
65+
66+
export * from './types';
67+
=== monorepo/pkg2/dist/types.d.ts ===
68+
69+
export * from '@raymondfeng/pkg1';

0 commit comments

Comments
 (0)