Skip to content

Commit 562e465

Browse files
authored
Update --infer-tsconfig to skip the allowJs option when there exist TS files (#90)
Fixes #87. Previously, we always included the `allowJs` option when using `--infer-tsconfig`. However, this behavior was undesirable because TypeScript package repos include a large amount of generated JavaScript code that should not be indexed. This commit changes the behavior so that we only use `allowJs` when the project doesn't have any TypeScript files. For example, the `npm/typescript` package (for the TypeScript compiler itself) times out when we index with `allowJs` while it completes in a few seconds without `allowJs`. It's OK to skip the JavaScript files since the TypeScript files include the definitions for the JavaScript code.
1 parent d5cc7ac commit 562e465

File tree

6 files changed

+78
-1
lines changed

6 files changed

+78
-1
lines changed

snapshots/inferTsConfig/js-project/hello.js

Whitespace-only changes.

snapshots/inferTsConfig/ts-project/hello.js

Whitespace-only changes.

snapshots/inferTsConfig/ts-project/hello.ts

Whitespace-only changes.

src/inferTsConfig.test.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { join } from 'path'
2+
import * as process from 'process'
3+
4+
import { test } from 'uvu'
5+
6+
import { allowJsConfig, inferTsConfig, noJsConfig } from './inferTsConfig'
7+
8+
const inputDirectory = join(process.cwd(), 'snapshots', 'inferTsConfig')
9+
10+
function checkDirectory(name: string, expected: string): void {
11+
test(name, () => {
12+
const directory = join(inputDirectory, name)
13+
const obtained = inferTsConfig(directory)
14+
if (obtained !== expected) {
15+
throw new Error(`expected ('${expected}') != obtained ('${obtained}')`)
16+
}
17+
})
18+
}
19+
20+
checkDirectory('js-project', allowJsConfig)
21+
checkDirectory('ts-project', noJsConfig)

src/inferTsConfig.ts

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import * as fs from 'fs'
2+
import * as path from 'path'
3+
4+
/**
5+
* To limit the risk of making the `inferTsConfig` run for a very long time, we
6+
* stop the file traversal after visiting this number of files.
7+
*/
8+
const maximumFileTraversalCount = 1_000
9+
10+
/** The TS config we use to index JavaScript files. */
11+
export const allowJsConfig = '{"compilerOptions":{"allowJs":true}}'
12+
13+
/** The TS config we use to index only TypeScript files. */
14+
export const noJsConfig = '{}'
15+
16+
/**
17+
* Returns the configuration that should be used for tsconfig.json in the provided path.
18+
*
19+
* If the directory contains at least one `*.{ts,tsx}` file then the config will be empty (`{}`).
20+
* If the directory doesn't contains one `*.{ts,tsx}` file then the config will
21+
*/
22+
export function inferTsConfig(projectPath: string): string {
23+
let hasTypeScriptFile = false
24+
let hasJavaScriptFile = false
25+
let visitedFileCount = 0
26+
const visitPath = (directory: string): { stop: boolean } => {
27+
if (directory.endsWith('.ts') || directory.endsWith('.tsx')) {
28+
hasTypeScriptFile = true
29+
return { stop: true }
30+
}
31+
if (directory.endsWith('.js') || directory.endsWith('.jsx')) {
32+
hasJavaScriptFile = true
33+
}
34+
if (!fs.statSync(directory).isDirectory()) {
35+
return { stop: false }
36+
}
37+
for (const child of fs.readdirSync(directory)) {
38+
visitedFileCount++
39+
if (visitedFileCount > maximumFileTraversalCount) {
40+
return { stop: true }
41+
}
42+
const fullPath = path.resolve(directory, child)
43+
const recursiveWalk = visitPath(fullPath)
44+
if (recursiveWalk.stop) {
45+
return recursiveWalk
46+
}
47+
}
48+
return { stop: false }
49+
}
50+
visitPath(projectPath)
51+
if (hasTypeScriptFile || !hasJavaScriptFile) {
52+
return noJsConfig
53+
}
54+
return allowJsConfig
55+
}

src/main.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as ts from 'typescript'
99

1010
import packageJson from '../package.json'
1111

12+
import { inferTsConfig } from './inferTsConfig'
1213
import * as lsif from './lsif'
1314
import { ProjectIndexer } from './ProjectIndexer'
1415

@@ -146,7 +147,7 @@ function indexSingleProject(options: ProjectOptions): void {
146147
}
147148
if (!ts.sys.fileExists(tsconfigFileName)) {
148149
if (options.inferTsconfig) {
149-
fs.writeFileSync(tsconfigFileName, '{"compilerOptions":{"allowJs":true}}')
150+
fs.writeFileSync(tsconfigFileName, inferTsConfig(projectPath))
150151
} else {
151152
console.error(`- ${options.projectDisplayName} (missing tsconfig.json)`)
152153
return

0 commit comments

Comments
 (0)