agentmap 0.7.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +96 -0
- package/README.md +24 -0
- package/dist/cli.js +44 -12
- package/dist/cli.js.map +1 -1
- package/dist/extract/definitions.js +12 -12
- package/dist/extract/definitions.js.map +1 -1
- package/dist/extract/definitions.test.js +30 -259
- package/dist/extract/definitions.test.js.map +1 -1
- package/dist/extract/git-status.d.ts +11 -4
- package/dist/extract/git-status.d.ts.map +1 -1
- package/dist/extract/git-status.js +21 -16
- package/dist/extract/git-status.js.map +1 -1
- package/dist/extract/markdown.js +1 -1
- package/dist/extract/markdown.test.js +3 -3
- package/dist/extract/markdown.test.js.map +1 -1
- package/dist/extract/marker.js +1 -1
- package/dist/extract/marker.test.js +4 -4
- package/dist/extract/marker.test.js.map +1 -1
- package/dist/extract/submodules.d.ts +12 -0
- package/dist/extract/submodules.d.ts.map +1 -0
- package/dist/extract/submodules.js +234 -0
- package/dist/extract/submodules.js.map +1 -0
- package/dist/extract/submodules.test.d.ts +2 -0
- package/dist/extract/submodules.test.d.ts.map +1 -0
- package/dist/extract/submodules.test.js +84 -0
- package/dist/extract/submodules.test.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -9
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +10 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +41 -0
- package/dist/logger.js.map +1 -0
- package/dist/map/builder.d.ts +3 -3
- package/dist/map/builder.d.ts.map +1 -1
- package/dist/map/builder.js +59 -9
- package/dist/map/builder.js.map +1 -1
- package/dist/map/builder.test.d.ts +2 -0
- package/dist/map/builder.test.d.ts.map +1 -0
- package/dist/map/builder.test.js +66 -0
- package/dist/map/builder.test.js.map +1 -0
- package/dist/map/truncate.d.ts +7 -3
- package/dist/map/truncate.d.ts.map +1 -1
- package/dist/map/truncate.js +90 -9
- package/dist/map/truncate.js.map +1 -1
- package/dist/map/yaml.d.ts.map +1 -1
- package/dist/map/yaml.js +13 -3
- package/dist/map/yaml.js.map +1 -1
- package/dist/scanner.d.ts +9 -2
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +172 -49
- package/dist/scanner.js.map +1 -1
- package/dist/scanner.test.d.ts +2 -0
- package/dist/scanner.test.d.ts.map +1 -0
- package/dist/scanner.test.js +84 -0
- package/dist/scanner.test.js.map +1 -0
- package/dist/test-helpers/git-test-helpers.d.ts +13 -0
- package/dist/test-helpers/git-test-helpers.d.ts.map +1 -0
- package/dist/test-helpers/git-test-helpers.js +48 -0
- package/dist/test-helpers/git-test-helpers.js.map +1 -0
- package/dist/types.d.ts +42 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +15 -3
- package/src/cli.ts +164 -0
- package/src/extract/definitions.test.ts +2040 -0
- package/src/extract/definitions.ts +379 -0
- package/src/extract/git-status.test.ts +507 -0
- package/src/extract/git-status.ts +359 -0
- package/src/extract/markdown.test.ts +159 -0
- package/src/extract/markdown.ts +202 -0
- package/src/extract/marker.test.ts +566 -0
- package/src/extract/marker.ts +398 -0
- package/src/extract/submodules.test.ts +95 -0
- package/src/extract/submodules.ts +269 -0
- package/src/extract/utils.ts +27 -0
- package/src/index.ts +106 -0
- package/src/languages/cpp.ts +129 -0
- package/src/languages/go.ts +72 -0
- package/src/languages/index.ts +231 -0
- package/src/languages/javascript.ts +33 -0
- package/src/languages/python.ts +41 -0
- package/src/languages/rust.ts +72 -0
- package/src/languages/typescript.ts +74 -0
- package/src/languages/zig.ts +106 -0
- package/src/logger.ts +55 -0
- package/src/map/builder.test.ts +72 -0
- package/src/map/builder.ts +175 -0
- package/src/map/truncate.ts +188 -0
- package/src/map/yaml.ts +66 -0
- package/src/parser/index.ts +53 -0
- package/src/parser/languages.ts +64 -0
- package/src/scanner.test.ts +95 -0
- package/src/scanner.ts +364 -0
- package/src/test-helpers/git-test-helpers.ts +62 -0
- package/src/types.ts +191 -0
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
import { beforeAll, describe, expect, test } from 'bun:test'
|
|
2
|
+
import { writeFile, unlink, mkdir } from 'fs/promises'
|
|
3
|
+
import { join } from 'path'
|
|
4
|
+
import { tmpdir } from 'os'
|
|
5
|
+
import { extractMarker } from './marker.js'
|
|
6
|
+
import { initParser } from '../parser/index.js'
|
|
7
|
+
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Setup
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
beforeAll(async () => {
|
|
13
|
+
await initParser()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
const TEST_DIR = join(tmpdir(), 'agentmap-marker-test')
|
|
17
|
+
|
|
18
|
+
async function testFile(filename: string, content: string): Promise<string | undefined> {
|
|
19
|
+
await mkdir(TEST_DIR, { recursive: true })
|
|
20
|
+
const filepath = join(TEST_DIR, filename)
|
|
21
|
+
await writeFile(filepath, content, 'utf8')
|
|
22
|
+
try {
|
|
23
|
+
const result = await extractMarker(filepath)
|
|
24
|
+
return result.found ? result.description : undefined
|
|
25
|
+
} finally {
|
|
26
|
+
await unlink(filepath).catch(() => {})
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// TypeScript / JavaScript
|
|
32
|
+
// ============================================================================
|
|
33
|
+
|
|
34
|
+
describe('TypeScript/JavaScript', () => {
|
|
35
|
+
test('single line // comment', async () => {
|
|
36
|
+
const desc = await testFile('test.ts', `// This is a header comment.
|
|
37
|
+
|
|
38
|
+
export function foo() {}
|
|
39
|
+
`)
|
|
40
|
+
expect(desc).toMatchInlineSnapshot(`"This is a header comment."`)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('multiple // comments', async () => {
|
|
44
|
+
const desc = await testFile('test.ts', `// First line of description.
|
|
45
|
+
// Second line continues.
|
|
46
|
+
// Third line ends.
|
|
47
|
+
|
|
48
|
+
export function foo() {}
|
|
49
|
+
`)
|
|
50
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
51
|
+
"First line of description.
|
|
52
|
+
Second line continues.
|
|
53
|
+
Third line ends."
|
|
54
|
+
`)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('block comment /* */', async () => {
|
|
58
|
+
const desc = await testFile('test.ts', `/* This is a block comment. */
|
|
59
|
+
|
|
60
|
+
export function foo() {}
|
|
61
|
+
`)
|
|
62
|
+
expect(desc).toMatchInlineSnapshot(`"This is a block comment."`)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('multi-line block comment', async () => {
|
|
66
|
+
const desc = await testFile('test.ts', `/*
|
|
67
|
+
* JSDoc style comment.
|
|
68
|
+
* With multiple lines.
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
export function foo() {}
|
|
72
|
+
`)
|
|
73
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
74
|
+
"JSDoc style comment.
|
|
75
|
+
With multiple lines."
|
|
76
|
+
`)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('JSDoc /** style', async () => {
|
|
80
|
+
const desc = await testFile('test.ts', `/**
|
|
81
|
+
* Module description here.
|
|
82
|
+
* Another line of info.
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
export function foo() {}
|
|
86
|
+
`)
|
|
87
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
88
|
+
"Module description here.
|
|
89
|
+
Another line of info."
|
|
90
|
+
`)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test('no header comment returns undefined', async () => {
|
|
94
|
+
const desc = await testFile('test.ts', `export function foo() {}
|
|
95
|
+
`)
|
|
96
|
+
expect(desc).toBeUndefined()
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('.js extension works', async () => {
|
|
100
|
+
const desc = await testFile('test.js', `// JavaScript file header.
|
|
101
|
+
|
|
102
|
+
function foo() {}
|
|
103
|
+
`)
|
|
104
|
+
expect(desc).toMatchInlineSnapshot(`"JavaScript file header."`)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
test('.jsx extension works', async () => {
|
|
108
|
+
const desc = await testFile('test.jsx', `// React component file.
|
|
109
|
+
|
|
110
|
+
export function App() {}
|
|
111
|
+
`)
|
|
112
|
+
expect(desc).toMatchInlineSnapshot(`"React component file."`)
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
test('.tsx extension works', async () => {
|
|
116
|
+
const desc = await testFile('test.tsx', `// TypeScript React component.
|
|
117
|
+
|
|
118
|
+
export function App() {}
|
|
119
|
+
`)
|
|
120
|
+
expect(desc).toMatchInlineSnapshot(`"TypeScript React component."`)
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// Python
|
|
126
|
+
// ============================================================================
|
|
127
|
+
|
|
128
|
+
describe('Python', () => {
|
|
129
|
+
test('module docstring """', async () => {
|
|
130
|
+
const desc = await testFile('test.py', `"""
|
|
131
|
+
This is a module docstring.
|
|
132
|
+
It describes the module.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
def foo():
|
|
136
|
+
pass
|
|
137
|
+
`)
|
|
138
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
139
|
+
"This is a module docstring.
|
|
140
|
+
It describes the module."
|
|
141
|
+
`)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
test("module docstring '''", async () => {
|
|
145
|
+
const desc = await testFile('test.py', `'''
|
|
146
|
+
Single quote docstring.
|
|
147
|
+
Also works fine.
|
|
148
|
+
'''
|
|
149
|
+
|
|
150
|
+
def foo():
|
|
151
|
+
pass
|
|
152
|
+
`)
|
|
153
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
154
|
+
"Single quote docstring.
|
|
155
|
+
Also works fine."
|
|
156
|
+
`)
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
test('single line docstring', async () => {
|
|
160
|
+
const desc = await testFile('test.py', `"""Single line docstring."""
|
|
161
|
+
|
|
162
|
+
def foo():
|
|
163
|
+
pass
|
|
164
|
+
`)
|
|
165
|
+
expect(desc).toMatchInlineSnapshot(`"Single line docstring."`)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
test('# hash comments', async () => {
|
|
169
|
+
const desc = await testFile('test.py', `# Hash comment header.
|
|
170
|
+
# Second line of hash comment.
|
|
171
|
+
|
|
172
|
+
def foo():
|
|
173
|
+
pass
|
|
174
|
+
`)
|
|
175
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
176
|
+
"Hash comment header.
|
|
177
|
+
Second line of hash comment."
|
|
178
|
+
`)
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
test('shebang is skipped, docstring extracted', async () => {
|
|
182
|
+
const desc = await testFile('test.py', `#!/usr/bin/env python3
|
|
183
|
+
"""Module with shebang."""
|
|
184
|
+
|
|
185
|
+
def foo():
|
|
186
|
+
pass
|
|
187
|
+
`)
|
|
188
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
189
|
+
"#!/usr/bin/env python3
|
|
190
|
+
Module with shebang."
|
|
191
|
+
`)
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
test('.pyi extension works', async () => {
|
|
195
|
+
const desc = await testFile('test.pyi', `"""Type stub file."""
|
|
196
|
+
|
|
197
|
+
def foo() -> None: ...
|
|
198
|
+
`)
|
|
199
|
+
expect(desc).toMatchInlineSnapshot(`"Type stub file."`)
|
|
200
|
+
})
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
// ============================================================================
|
|
204
|
+
// Rust
|
|
205
|
+
// ============================================================================
|
|
206
|
+
|
|
207
|
+
describe('Rust', () => {
|
|
208
|
+
test('//! inner doc comments', async () => {
|
|
209
|
+
const desc = await testFile('test.rs', `//! Module documentation.
|
|
210
|
+
//! Describes the crate.
|
|
211
|
+
|
|
212
|
+
fn main() {}
|
|
213
|
+
`)
|
|
214
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
215
|
+
"Module documentation.
|
|
216
|
+
Describes the crate."
|
|
217
|
+
`)
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
test('// regular comments', async () => {
|
|
221
|
+
const desc = await testFile('test.rs', `// Regular comment header.
|
|
222
|
+
// Another line.
|
|
223
|
+
|
|
224
|
+
fn main() {}
|
|
225
|
+
`)
|
|
226
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
227
|
+
"Regular comment header.
|
|
228
|
+
Another line."
|
|
229
|
+
`)
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
test('/* block comment */', async () => {
|
|
233
|
+
const desc = await testFile('test.rs', `/* Block comment in Rust. */
|
|
234
|
+
|
|
235
|
+
fn main() {}
|
|
236
|
+
`)
|
|
237
|
+
expect(desc).toMatchInlineSnapshot(`"Block comment in Rust."`)
|
|
238
|
+
})
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
// ============================================================================
|
|
242
|
+
// Go
|
|
243
|
+
// ============================================================================
|
|
244
|
+
|
|
245
|
+
describe('Go', () => {
|
|
246
|
+
test('// line comments', async () => {
|
|
247
|
+
const desc = await testFile('test.go', `// Package main provides the entry point.
|
|
248
|
+
// It handles CLI arguments.
|
|
249
|
+
|
|
250
|
+
package main
|
|
251
|
+
|
|
252
|
+
func main() {}
|
|
253
|
+
`)
|
|
254
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
255
|
+
"Package main provides the entry point.
|
|
256
|
+
It handles CLI arguments."
|
|
257
|
+
`)
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
test('/* block comment */', async () => {
|
|
261
|
+
const desc = await testFile('test.go', `/*
|
|
262
|
+
Package utils provides helper functions.
|
|
263
|
+
Used throughout the application.
|
|
264
|
+
*/
|
|
265
|
+
|
|
266
|
+
package utils
|
|
267
|
+
`)
|
|
268
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
269
|
+
"Package utils provides helper functions.
|
|
270
|
+
Used throughout the application."
|
|
271
|
+
`)
|
|
272
|
+
})
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
// ============================================================================
|
|
276
|
+
// Directives (use strict, use client, etc.)
|
|
277
|
+
// ============================================================================
|
|
278
|
+
|
|
279
|
+
describe('Directives', () => {
|
|
280
|
+
test('"use strict" followed by comment', async () => {
|
|
281
|
+
const desc = await testFile('test.ts', `"use strict"
|
|
282
|
+
// This is the header comment.
|
|
283
|
+
// After the directive.
|
|
284
|
+
|
|
285
|
+
function foo() {}
|
|
286
|
+
`)
|
|
287
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
288
|
+
"This is the header comment.
|
|
289
|
+
After the directive."
|
|
290
|
+
`)
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
test('"use client" followed by comment', async () => {
|
|
294
|
+
const desc = await testFile('test.tsx', `"use client"
|
|
295
|
+
// React client component.
|
|
296
|
+
// Renders on the client side.
|
|
297
|
+
|
|
298
|
+
export function App() {}
|
|
299
|
+
`)
|
|
300
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
301
|
+
"React client component.
|
|
302
|
+
Renders on the client side."
|
|
303
|
+
`)
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
test('"use server" followed by comment', async () => {
|
|
307
|
+
const desc = await testFile('test.ts', `"use server"
|
|
308
|
+
// Server action module.
|
|
309
|
+
|
|
310
|
+
export async function submitForm() {}
|
|
311
|
+
`)
|
|
312
|
+
expect(desc).toMatchInlineSnapshot(`"Server action module."`)
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
test('single quotes directive works', async () => {
|
|
316
|
+
const desc = await testFile('test.js', `'use strict'
|
|
317
|
+
// Header after single-quote directive.
|
|
318
|
+
|
|
319
|
+
function foo() {}
|
|
320
|
+
`)
|
|
321
|
+
expect(desc).toMatchInlineSnapshot(`"Header after single-quote directive."`)
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
test('directive with no comment returns undefined', async () => {
|
|
325
|
+
const desc = await testFile('test.ts', `"use strict"
|
|
326
|
+
|
|
327
|
+
function foo() {}
|
|
328
|
+
`)
|
|
329
|
+
expect(desc).toBeUndefined()
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
test('directive followed by block comment', async () => {
|
|
333
|
+
const desc = await testFile('test.ts', `"use strict"
|
|
334
|
+
/**
|
|
335
|
+
* Module description.
|
|
336
|
+
* After directive.
|
|
337
|
+
*/
|
|
338
|
+
|
|
339
|
+
export function foo() {}
|
|
340
|
+
`)
|
|
341
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
342
|
+
"Module description.
|
|
343
|
+
After directive."
|
|
344
|
+
`)
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
test('shebang + directive + comment', async () => {
|
|
348
|
+
const desc = await testFile('test.ts', `#!/usr/bin/env node
|
|
349
|
+
"use strict"
|
|
350
|
+
// CLI tool for processing data.
|
|
351
|
+
// Handles input and output.
|
|
352
|
+
|
|
353
|
+
function main() {}
|
|
354
|
+
`)
|
|
355
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
356
|
+
"#!/usr/bin/env node
|
|
357
|
+
CLI tool for processing data.
|
|
358
|
+
Handles input and output."
|
|
359
|
+
`)
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
test('shebang + comment (no directive)', async () => {
|
|
363
|
+
const desc = await testFile('test.js', `#!/usr/bin/env node
|
|
364
|
+
// Simple script runner.
|
|
365
|
+
|
|
366
|
+
console.log("hello")
|
|
367
|
+
`)
|
|
368
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
369
|
+
"#!/usr/bin/env node
|
|
370
|
+
Simple script runner."
|
|
371
|
+
`)
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
test('shebang + use client + comment', async () => {
|
|
375
|
+
const desc = await testFile('test.tsx', `#!/usr/bin/env node
|
|
376
|
+
"use client"
|
|
377
|
+
// React client app entry.
|
|
378
|
+
|
|
379
|
+
export function App() {}
|
|
380
|
+
`)
|
|
381
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
382
|
+
"#!/usr/bin/env node
|
|
383
|
+
React client app entry."
|
|
384
|
+
`)
|
|
385
|
+
})
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
// ============================================================================
|
|
389
|
+
// License Comments (should be skipped)
|
|
390
|
+
// ============================================================================
|
|
391
|
+
|
|
392
|
+
describe('License comments', () => {
|
|
393
|
+
test('Meta/Facebook style license header is skipped', async () => {
|
|
394
|
+
const desc = await testFile('test.ts', `/**
|
|
395
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
396
|
+
*
|
|
397
|
+
* This source code is licensed under the MIT license found in the
|
|
398
|
+
* LICENSE file in the root directory of this source tree.
|
|
399
|
+
*/
|
|
400
|
+
|
|
401
|
+
// This is the actual file description.
|
|
402
|
+
// It describes what the file does.
|
|
403
|
+
|
|
404
|
+
export function foo() {}
|
|
405
|
+
`)
|
|
406
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
407
|
+
"This is the actual file description.
|
|
408
|
+
It describes what the file does."
|
|
409
|
+
`)
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
test('MIT license header is skipped', async () => {
|
|
413
|
+
const desc = await testFile('test.ts', `/**
|
|
414
|
+
* MIT License
|
|
415
|
+
*
|
|
416
|
+
* Copyright (c) 2024 Some Company
|
|
417
|
+
*
|
|
418
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
419
|
+
* of this software and associated documentation files.
|
|
420
|
+
*/
|
|
421
|
+
|
|
422
|
+
// File description after license.
|
|
423
|
+
|
|
424
|
+
export function foo() {}
|
|
425
|
+
`)
|
|
426
|
+
expect(desc).toMatchInlineSnapshot(`"File description after license."`)
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
test('SPDX license identifier is skipped', async () => {
|
|
430
|
+
const desc = await testFile('test.ts', `// SPDX-License-Identifier: MIT
|
|
431
|
+
|
|
432
|
+
// Actual description of the module.
|
|
433
|
+
// More details here.
|
|
434
|
+
|
|
435
|
+
export function foo() {}
|
|
436
|
+
`)
|
|
437
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
438
|
+
"Actual description of the module.
|
|
439
|
+
More details here."
|
|
440
|
+
`)
|
|
441
|
+
})
|
|
442
|
+
|
|
443
|
+
test('BSD license is skipped', async () => {
|
|
444
|
+
const desc = await testFile('test.go', `/*
|
|
445
|
+
* Copyright 2024 Some Corp. All rights reserved.
|
|
446
|
+
* Redistribution and use in source and binary forms are permitted.
|
|
447
|
+
*/
|
|
448
|
+
|
|
449
|
+
// Package main handles the CLI.
|
|
450
|
+
|
|
451
|
+
package main
|
|
452
|
+
`)
|
|
453
|
+
expect(desc).toMatchInlineSnapshot(`"Package main handles the CLI."`)
|
|
454
|
+
})
|
|
455
|
+
|
|
456
|
+
test('Python license docstring is skipped', async () => {
|
|
457
|
+
const desc = await testFile('test.py', `"""
|
|
458
|
+
Copyright (c) 2024 Company Inc.
|
|
459
|
+
All Rights Reserved.
|
|
460
|
+
"""
|
|
461
|
+
|
|
462
|
+
# This module handles data processing.
|
|
463
|
+
# It provides utilities for ETL workflows.
|
|
464
|
+
|
|
465
|
+
def process():
|
|
466
|
+
pass
|
|
467
|
+
`)
|
|
468
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
469
|
+
"This module handles data processing.
|
|
470
|
+
It provides utilities for ETL workflows."
|
|
471
|
+
`)
|
|
472
|
+
})
|
|
473
|
+
|
|
474
|
+
test('multiple consecutive license comments are skipped', async () => {
|
|
475
|
+
const desc = await testFile('test.ts', `// Copyright 2024 Company
|
|
476
|
+
// Licensed under Apache 2.0
|
|
477
|
+
|
|
478
|
+
// This is the real description.
|
|
479
|
+
|
|
480
|
+
export function foo() {}
|
|
481
|
+
`)
|
|
482
|
+
expect(desc).toMatchInlineSnapshot(`"This is the real description."`)
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
test('license only file returns undefined', async () => {
|
|
486
|
+
const desc = await testFile('test.ts', `/**
|
|
487
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
488
|
+
*
|
|
489
|
+
* This source code is licensed under the MIT license found in the
|
|
490
|
+
* LICENSE file in the root directory of this source tree.
|
|
491
|
+
*/
|
|
492
|
+
|
|
493
|
+
export function foo() {}
|
|
494
|
+
`)
|
|
495
|
+
expect(desc).toBeUndefined()
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
test('Rust inner doc license is skipped', async () => {
|
|
499
|
+
const desc = await testFile('test.rs', `//! Copyright 2024 Rust Foundation
|
|
500
|
+
//! This source code is licensed under MIT.
|
|
501
|
+
|
|
502
|
+
//! This module provides HTTP utilities.
|
|
503
|
+
//! Use it for making web requests.
|
|
504
|
+
|
|
505
|
+
fn main() {}
|
|
506
|
+
`)
|
|
507
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
508
|
+
"This module provides HTTP utilities.
|
|
509
|
+
Use it for making web requests."
|
|
510
|
+
`)
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
test('non-license comment is not skipped', async () => {
|
|
514
|
+
const desc = await testFile('test.ts', `// This module handles user authentication.
|
|
515
|
+
// It provides login and logout functionality.
|
|
516
|
+
|
|
517
|
+
export function login() {}
|
|
518
|
+
`)
|
|
519
|
+
expect(desc).toMatchInlineSnapshot(`
|
|
520
|
+
"This module handles user authentication.
|
|
521
|
+
It provides login and logout functionality."
|
|
522
|
+
`)
|
|
523
|
+
})
|
|
524
|
+
})
|
|
525
|
+
|
|
526
|
+
// ============================================================================
|
|
527
|
+
// Edge Cases
|
|
528
|
+
// ============================================================================
|
|
529
|
+
|
|
530
|
+
describe('Edge cases', () => {
|
|
531
|
+
test('empty file returns undefined', async () => {
|
|
532
|
+
const desc = await testFile('test.ts', ``)
|
|
533
|
+
expect(desc).toBeUndefined()
|
|
534
|
+
})
|
|
535
|
+
|
|
536
|
+
test('whitespace only returns undefined', async () => {
|
|
537
|
+
const desc = await testFile('test.ts', `
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
`)
|
|
541
|
+
expect(desc).toBeUndefined()
|
|
542
|
+
})
|
|
543
|
+
|
|
544
|
+
test('unsupported extension returns undefined', async () => {
|
|
545
|
+
const desc = await testFile('test.txt', `// This is a comment.
|
|
546
|
+
`)
|
|
547
|
+
expect(desc).toBeUndefined()
|
|
548
|
+
})
|
|
549
|
+
|
|
550
|
+
test('description limited to 20 lines with truncation indicator', async () => {
|
|
551
|
+
const lines = Array.from({ length: 30 }, (_, i) => `// Line ${i + 1}`).join('\n')
|
|
552
|
+
const desc = await testFile('test.ts', lines + '\n\nexport function foo() {}')
|
|
553
|
+
const descLines = desc?.split('\n') ?? []
|
|
554
|
+
// 20 content lines + 1 truncation indicator
|
|
555
|
+
expect(descLines.length).toBe(21)
|
|
556
|
+
expect(descLines[20]).toBe('... and 10 more lines')
|
|
557
|
+
})
|
|
558
|
+
|
|
559
|
+
test('empty comment returns undefined (no meaningful description)', async () => {
|
|
560
|
+
const desc = await testFile('test.ts', `//
|
|
561
|
+
|
|
562
|
+
export function foo() {}
|
|
563
|
+
`)
|
|
564
|
+
expect(desc).toBeUndefined()
|
|
565
|
+
})
|
|
566
|
+
})
|