Skip to content

Commit c5ccac1

Browse files
committed
feat: placement api
1 parent dcfad92 commit c5ccac1

File tree

1,282 files changed

+14513
-14471
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,282 files changed

+14513
-14471
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { BiMap } from '../bimap/bimap';
4+
5+
describe('BiMap', () => {
6+
it('covers the full public interface', () => {
7+
const bimap = new BiMap<number, string>();
8+
// set and get
9+
expect(bimap.set(1, 'a')).toBe(bimap);
10+
expect(bimap.set(2, 'b')).toBe(bimap);
11+
// get, getKey
12+
expect(bimap.get(1)).toBe('a');
13+
expect(bimap.get(2)).toBe('b');
14+
expect(bimap.getKey('a')).toBe(1);
15+
expect(bimap.getKey('b')).toBe(2);
16+
// hasKey, hasValue
17+
expect(bimap.hasKey(1)).toBe(true);
18+
expect(bimap.hasKey(2)).toBe(true);
19+
expect(bimap.hasKey(3)).toBe(false);
20+
expect(bimap.hasValue('a')).toBe(true);
21+
expect(bimap.hasValue('b')).toBe(true);
22+
expect(bimap.hasValue('c')).toBe(false);
23+
// keys, values, entries
24+
expect(Array.from(bimap.keys())).toEqual([1, 2]);
25+
expect(Array.from(bimap.values())).toEqual(['a', 'b']);
26+
expect(Array.from(bimap.entries())).toEqual([
27+
[1, 'a'],
28+
[2, 'b'],
29+
]);
30+
// Symbol.iterator
31+
expect(Array.from(bimap)).toEqual([
32+
[1, 'a'],
33+
[2, 'b'],
34+
]);
35+
// size
36+
expect(bimap.size).toBe(2);
37+
// delete by key
38+
expect(bimap.delete(1)).toBe(true);
39+
expect(bimap.hasKey(1)).toBe(false);
40+
expect(bimap.hasValue('a')).toBe(false);
41+
// delete by value
42+
expect(bimap.deleteValue('b')).toBe(true);
43+
expect(bimap.hasKey(2)).toBe(false);
44+
expect(bimap.hasValue('b')).toBe(false);
45+
// After all deletes
46+
expect(bimap.size).toBe(0);
47+
// Setting again to check overwrite
48+
bimap.set(1, 'x');
49+
bimap.set(2, 'y');
50+
expect(bimap.get(1)).toBe('x');
51+
expect(bimap.get(2)).toBe('y');
52+
// Overwrite value for existing key
53+
bimap.set(1, 'z');
54+
expect(bimap.get(1)).toBe('z');
55+
expect(bimap.getKey('z')).toBe(1);
56+
// Overwrite key for existing value
57+
bimap.set(3, 'z');
58+
expect(bimap.getKey('z')).toBe(3);
59+
expect(bimap.get(1)).toBeUndefined();
60+
// Iteration after overwrite
61+
expect(Array.from(bimap)).toEqual([
62+
[2, 'y'],
63+
[3, 'z'],
64+
]);
65+
});
66+
});
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import type { IBiMap } from '../bimap/types';
4+
import type { IBinding } from '../bindings/types';
5+
import { createBinding, mergeBindings } from '../bindings/utils';
6+
import type { ISymbolMeta } from '../extensions/types';
7+
import type { IFileOut } from '../files/types';
8+
import type { ISymbolOut } from '../symbols/types';
9+
10+
function makeBiMap(entries: [number, string][] = []): IBiMap<number, string> {
11+
const map = new Map<number, string>(entries);
12+
const reverse = new Map<string, number>(entries.map(([k, v]) => [v, k]));
13+
const bimap: IBiMap<number, string> = {
14+
delete: (key: number) => {
15+
const value = map.get(key);
16+
map.delete(key);
17+
if (value) reverse.delete(value);
18+
return true;
19+
},
20+
deleteValue: (value: string) => {
21+
const key = reverse.get(value);
22+
reverse.delete(value);
23+
if (key) map.delete(key);
24+
return true;
25+
},
26+
entries: () => map.entries(),
27+
get: (key: number) => map.get(key),
28+
getKey: (value: string) => reverse.get(value),
29+
hasKey: (key: number) => map.has(key),
30+
hasValue: (value: string) => reverse.has(value),
31+
keys() {
32+
return map.keys();
33+
},
34+
set: (key: number, value: string): IBiMap<number, string> => {
35+
map.set(key, value);
36+
reverse.set(value, key);
37+
return bimap;
38+
},
39+
size: 0,
40+
values() {
41+
return map.values();
42+
},
43+
[Symbol.iterator]() {
44+
return map[Symbol.iterator]();
45+
},
46+
};
47+
return bimap;
48+
}
49+
50+
const makeFile = (
51+
resolvedNames: IBiMap<number, string> = makeBiMap(),
52+
id: number = 1,
53+
): IFileOut => ({
54+
extension: 'ts',
55+
id,
56+
name: '',
57+
path: '',
58+
resolvedNames,
59+
selector: [],
60+
symbols: { body: [], exports: [], imports: [] },
61+
});
62+
63+
const makeSymbol = (
64+
id: number,
65+
placeholder: string,
66+
meta: ISymbolMeta = {},
67+
name?: string,
68+
): ISymbolOut => ({
69+
exportFrom: [],
70+
id,
71+
meta,
72+
name,
73+
placeholder,
74+
});
75+
76+
describe('createBinding', () => {
77+
it('creates a named binding by default', () => {
78+
const file = makeFile(makeBiMap([[1, 'Foo']]));
79+
const symbol = makeSymbol(
80+
1,
81+
'Foo',
82+
{ importKind: 'named', kind: 'value' },
83+
'Foo',
84+
);
85+
const symbolFile = makeFile(makeBiMap([[1, 'Foo']]));
86+
const binding = createBinding({
87+
file,
88+
modulePath: './foo',
89+
symbol,
90+
symbolFile,
91+
});
92+
expect(binding).toEqual({
93+
aliases: {},
94+
from: './foo',
95+
names: ['Foo'],
96+
typeNames: [],
97+
});
98+
});
99+
100+
it('creates a default binding', () => {
101+
const file = makeFile();
102+
const symbol = makeSymbol(
103+
2,
104+
'Bar',
105+
{ importKind: 'default', kind: 'value' },
106+
'Bar',
107+
);
108+
const symbolFile = makeFile();
109+
const binding = createBinding({
110+
file,
111+
modulePath: './bar',
112+
symbol,
113+
symbolFile,
114+
});
115+
expect(binding).toEqual({
116+
aliases: {},
117+
defaultBinding: 'Bar',
118+
from: './bar',
119+
names: [],
120+
typeDefaultBinding: undefined,
121+
typeNames: [],
122+
});
123+
});
124+
125+
it('creates a namespace binding', () => {
126+
const file = makeFile();
127+
const symbol = makeSymbol(
128+
3,
129+
'Baz',
130+
{ importKind: 'namespace', kind: 'value' },
131+
'Baz',
132+
);
133+
const symbolFile = makeFile();
134+
const binding = createBinding({
135+
file,
136+
modulePath: './baz',
137+
symbol,
138+
symbolFile,
139+
});
140+
expect(binding).toEqual({
141+
aliases: {},
142+
from: './baz',
143+
names: [],
144+
namespaceBinding: 'Baz',
145+
typeNames: [],
146+
typeNamespaceBinding: undefined,
147+
});
148+
});
149+
150+
it('creates type names for type symbols', () => {
151+
const file = makeFile(makeBiMap([[4, 'Qux']]));
152+
const symbol = makeSymbol(
153+
4,
154+
'Qux',
155+
{ importKind: 'named', kind: 'type' },
156+
'Qux',
157+
);
158+
const symbolFile = makeFile(makeBiMap([[4, 'Qux']]));
159+
const binding = createBinding({
160+
file,
161+
modulePath: './qux',
162+
symbol,
163+
symbolFile,
164+
});
165+
expect(binding).toEqual({
166+
aliases: {},
167+
from: './qux',
168+
names: ['Qux'],
169+
typeNames: ['Qux'],
170+
});
171+
});
172+
});
173+
174+
describe('mergeBindings', () => {
175+
it('merges aliases, names, and typeNames', () => {
176+
const target: IBinding = {
177+
aliases: { Foo: 'Bar' },
178+
from: './foo',
179+
names: ['Foo'],
180+
typeNames: ['Foo'],
181+
};
182+
const source: IBinding = {
183+
aliases: { Baz: 'Qux' },
184+
from: './foo',
185+
names: ['Baz'],
186+
typeNames: ['Baz'],
187+
};
188+
mergeBindings(target, source);
189+
expect(target).toEqual({
190+
aliases: { Baz: 'Qux', Foo: 'Bar' },
191+
from: './foo',
192+
names: ['Foo', 'Baz'],
193+
typeNames: ['Foo', 'Baz'],
194+
});
195+
});
196+
197+
it('merges default and namespace bindings', () => {
198+
const target: IBinding = {
199+
aliases: {},
200+
from: './foo',
201+
names: [],
202+
typeNames: [],
203+
};
204+
const source: IBinding = {
205+
aliases: {},
206+
defaultBinding: 'Default',
207+
from: './foo',
208+
names: [],
209+
namespaceBinding: 'NS',
210+
typeDefaultBinding: true,
211+
typeNames: [],
212+
typeNamespaceBinding: true,
213+
};
214+
mergeBindings(target, source);
215+
expect(target).toEqual({
216+
aliases: {},
217+
defaultBinding: 'Default',
218+
from: './foo',
219+
names: [],
220+
namespaceBinding: 'NS',
221+
typeDefaultBinding: true,
222+
typeNames: [],
223+
typeNamespaceBinding: true,
224+
});
225+
});
226+
});
File renamed without changes.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import * as index from '../index';
4+
5+
const constExports = ['createBinding', 'mergeBindings', 'Project', 'renderIds'];
6+
7+
// Type-level test: will fail to compile if any type export is missing or renamed
8+
export type _TypeExports = [
9+
index.BiMap<string, string>,
10+
index.Binding,
11+
index.ProjectRenderMeta,
12+
index.SymbolMeta,
13+
index.File,
14+
index.FileIn,
15+
index.Output,
16+
index.IProject,
17+
index.Renderer,
18+
index.Selector,
19+
index.Symbol,
20+
index.SymbolIn,
21+
];
22+
23+
describe('index exports', () => {
24+
it('should export all expected symbols', () => {
25+
for (const key of constExports) {
26+
expect(index).toHaveProperty(key);
27+
}
28+
});
29+
});

0 commit comments

Comments
 (0)