Skip to content

Commit f5192a2

Browse files
authored
Merge pull request #39 from sourcegraph/progress-bar
Fix #37, add progress bar
2 parents b8332c8 + 6776cae commit f5192a2

File tree

6 files changed

+109
-9
lines changed

6 files changed

+109
-9
lines changed

.github/workflows/sourcegraph.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ jobs:
1212
- run: yarn install
1313
- run: yarn global add ts-node
1414
- run: ts-node src/main.ts index
15-
- uses: actions/setup-go@v2
16-
with: { go-version: '1.17' }
1715
- name: Convert LSIF Typed into LSIF Graph
1816
run: |
1917
curl -Lo lsif-typed https://github.com/sourcegraph/lsif-typescript/releases/download/v0.1.8/lsif-typed && chmod +x lsif-typed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
2-
"$schema": "https://raw.githubusercontent.com/sourcegraph/sourcegraph/master/shared/src/schema/extension.schema.json",
32
"name": "@sourcegraph/lsif-typescript",
43
"version": "0.1.10",
54
"description": "LSIF indexer for TypeScript and JavaScript",
@@ -35,6 +34,8 @@
3534
"homepage": "https://github.com/sourcegraph/lsif-typescript#readme",
3635
"dependencies": {
3736
"google-protobuf": "^3.19.3",
37+
"pretty-ms": "^7.0.1",
38+
"progress": "^2.0.3",
3839
"typescript": "^4.5.4",
3940
"yargs": "^17.3.1"
4041
},
@@ -45,6 +46,8 @@
4546
"@types/diff": "5.0.2",
4647
"@types/google-protobuf": "3.15.5",
4748
"@types/node": "17.0.14",
49+
"@types/pretty-ms": "^5.0.1",
50+
"@types/progress": "^2.0.5",
4851
"@types/yargs": "17.0.9",
4952
"@typescript-eslint/eslint-plugin": "^5.14.0",
5053
"@typescript-eslint/parser": "^5.14.0",

src/ProjectIndexer.ts

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import { Writable as WritableStream } from 'node:stream'
12
import * as path from 'path'
23
import * as url from 'url'
34

5+
import prettyMilliseconds from 'pretty-ms'
6+
import ProgressBar from 'progress'
47
import * as ts from 'typescript'
58

69
import packageJson from '../package.json'
@@ -25,6 +28,7 @@ export class ProjectIndexer {
2528
this.packages = new Packages(options.projectRoot)
2629
}
2730
public index(): void {
31+
const startTimestamp = Date.now()
2832
this.options.writeIndex(
2933
new lsiftyped.Index({
3034
metadata: new lsiftyped.Metadata({
@@ -46,12 +50,46 @@ export class ProjectIndexer {
4650
`no source files in project root '${this.options.workspaceRoot}'`
4751
)
4852
}
53+
54+
const filesToIndex: ts.SourceFile[] = []
4955
// Visit every sourceFile in the program
50-
for (const sourceFile of this.program.getSourceFiles()) {
56+
for (const sourceFile of sourceFiles) {
5157
const includes = this.config.fileNames.includes(sourceFile.fileName)
5258
if (!includes) {
5359
continue
5460
}
61+
filesToIndex.push(sourceFile)
62+
}
63+
64+
const jobs = new ProgressBar(
65+
` ${this.options.projectDisplayName} [:bar] :current/:total :title`,
66+
{
67+
total: filesToIndex.length,
68+
renderThrottle: 100,
69+
incomplete: '_',
70+
complete: '#',
71+
width: 20,
72+
clear: true,
73+
stream: this.options.noProgressBar
74+
? writableNoopStream()
75+
: process.stderr,
76+
}
77+
)
78+
let lastWrite = Date.now()
79+
for (const sourceFile of filesToIndex) {
80+
const title = path.relative(
81+
this.options.workspaceRoot,
82+
sourceFile.fileName
83+
)
84+
jobs.tick({ title })
85+
if (this.options.noProgressBar) {
86+
const now = Date.now()
87+
const elapsed = now - lastWrite
88+
if (elapsed > 1000) {
89+
lastWrite = now
90+
process.stdout.write('.')
91+
}
92+
}
5593
const document = new lsif.lib.codeintel.lsiftyped.Document({
5694
relative_path: path.relative(
5795
this.options.workspaceRoot,
@@ -84,5 +122,21 @@ export class ProjectIndexer {
84122
)
85123
}
86124
}
125+
jobs.terminate()
126+
const elapsed = Date.now() - startTimestamp
127+
if (this.options.noProgressBar) {
128+
process.stdout.write('\n')
129+
}
130+
console.log(
131+
`+ ${this.options.projectDisplayName} (${prettyMilliseconds(elapsed)})`
132+
)
87133
}
88134
}
135+
136+
function writableNoopStream(): WritableStream {
137+
return new WritableStream({
138+
write(_unused1, _unused2, callback) {
139+
setImmediate(callback)
140+
},
141+
})
142+
}

src/main.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ for (const snapshotDirectory of snapshotDirectories) {
4242
lsifIndex({
4343
workspaceRoot: inputRoot,
4444
projectRoot: inputRoot,
45+
projectDisplayName: inputRoot,
4546
inferTSConfig: false,
4647
writeIndex: partialIndex => {
4748
if (partialIndex.metadata) {

src/main.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import * as child_process from 'child_process'
33
import * as fs from 'fs'
44
import * as path from 'path'
5+
import { cwd } from 'process'
56

67
import * as ts from 'typescript'
78
import * as yargs from 'yargs'
@@ -24,9 +25,15 @@ export interface Options {
2425
/** The directory containing a tsconfig.json file. */
2526
projectRoot: string
2627

28+
/** The display name of the project. */
29+
projectDisplayName: string
30+
2731
/** Whether to infer the tsconfig.json file, if it's missing. */
2832
inferTSConfig: boolean
2933

34+
/** If truthy, disables the progress bar. */
35+
noProgressBar?: boolean
36+
3037
/**
3138
* Callback to consume the generated LSIF Typed payload in a streaming fashion.
3239
*/
@@ -64,6 +71,11 @@ export function main(): void {
6471
default: 'dump.lsif-typed',
6572
describe: 'path to the output file',
6673
})
74+
yargs.option('noProgressBar', {
75+
type: 'boolean',
76+
default: `${!process.stderr.isTTY}`,
77+
describe: 'disable the progress bar',
78+
})
6779
},
6880
argv => {
6981
const workspaceRoot = argv.project as string
@@ -74,23 +86,31 @@ export function main(): void {
7486
const projects: string[] = yarnWorkspaces
7587
? listYarnWorkspaces(workspaceRoot)
7688
: [workspaceRoot]
77-
const output = fs.openSync(argv.output as string, 'w')
89+
let outputPath = argv.output as string
90+
if (!path.isAbsolute(outputPath)) {
91+
outputPath = path.resolve(cwd(), outputPath)
92+
}
93+
const output = fs.openSync(outputPath, 'w')
7894
try {
7995
// NOTE: we may want index these projects in parallel in the future.
8096
// We need to be careful about which order we index the projects because
8197
// they can have dependencies.
8298
for (const projectRoot of projects) {
99+
const projectDisplayName = projectRoot === '.' ? cwd() : projectRoot
83100
index({
84101
workspaceRoot,
85102
projectRoot,
103+
projectDisplayName,
86104
inferTSConfig,
105+
noProgressBar: argv.noProgressBar === true,
87106
writeIndex: (index): void => {
88107
fs.writeSync(output, index.serializeBinary())
89108
},
90109
})
91110
}
92111
} finally {
93112
fs.close(output)
113+
console.log(`done ${outputPath}`)
94114
}
95115
}
96116
)
@@ -142,9 +162,7 @@ export function index(options: Options): void {
142162
'{"compilerOptions":{"allowJs":true}}'
143163
)
144164
} else {
145-
console.error(
146-
`skipping project '${options.projectRoot}' because it's missing tsconfig.json (expected at ${tsconfigFileName})`
147-
)
165+
console.error(`- ${options.projectDisplayName} (missing tsconfig.json)`)
148166
return
149167
}
150168
}

yarn.lock

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,20 @@
440440
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
441441
integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
442442

443+
"@types/pretty-ms@^5.0.1":
444+
version "5.0.1"
445+
resolved "https://registry.yarnpkg.com/@types/pretty-ms/-/pretty-ms-5.0.1.tgz#f2f0d7be58caf8613d149053d446e0282ae11ff3"
446+
integrity sha512-FFR4uj0p47Yq6JCrOt7DCaiUJIw7t9Vh7wwt3bF6qq99QRqjSH/doEGZsIIgZqhDmwjBObVBkrn0ICm1pY+mPg==
447+
dependencies:
448+
pretty-ms "*"
449+
450+
"@types/progress@^2.0.5":
451+
version "2.0.5"
452+
resolved "https://registry.yarnpkg.com/@types/progress/-/progress-2.0.5.tgz#6e0febf3a82cc0ffdc1cebb4e56d6949fd108775"
453+
integrity sha512-ZYYVc/kSMkhH9W/4dNK/sLNra3cnkfT2nJyOAIDY+C2u6w72wa0s1aXAezVtbTsnN8HID1uhXCrLwDE2ZXpplg==
454+
dependencies:
455+
"@types/node" "*"
456+
443457
"@types/yargs-parser@*":
444458
version "21.0.0"
445459
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
@@ -2153,6 +2167,11 @@ parse-json@^5.0.0:
21532167
json-parse-even-better-errors "^2.3.0"
21542168
lines-and-columns "^1.1.6"
21552169

2170+
parse-ms@^2.1.0:
2171+
version "2.1.0"
2172+
resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d"
2173+
integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==
2174+
21562175
path-exists@^3.0.0:
21572176
version "3.0.0"
21582177
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
@@ -2218,7 +2237,14 @@ pretty-format@^26.6.2:
22182237
ansi-styles "^4.0.0"
22192238
react-is "^17.0.1"
22202239

2221-
progress@^2.0.0:
2240+
pretty-ms@*, pretty-ms@^7.0.1:
2241+
version "7.0.1"
2242+
resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-7.0.1.tgz#7d903eaab281f7d8e03c66f867e239dc32fb73e8"
2243+
integrity sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==
2244+
dependencies:
2245+
parse-ms "^2.1.0"
2246+
2247+
progress@^2.0.0, progress@^2.0.3:
22222248
version "2.0.3"
22232249
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
22242250
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==

0 commit comments

Comments
 (0)