Skip to content

Commit

Permalink
Add support for --build --verbose invocations
Browse files Browse the repository at this point in the history
This is super handy for debugging when a `--build` is failing for some
reason. The default reporting from `tsc` or `glint` itself isn't always
helpful: it tends to bottom out with a *symptom* like "some type is not
defined" without any way to get to the root cause of *why* that type is
not defined. Having `--verbose` available for a `--build` invocation
surfaces additional information, including which `references` are being
built or not, and why.
  • Loading branch information
chriskrycho committed Jun 16, 2023
1 parent 84f23ef commit ba0b3ee
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 0 deletions.
175 changes: 175 additions & 0 deletions packages/core/__tests__/cli/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,89 @@ describe('CLI: single-pass build mode typechecking', () => {
"
`);
});

describe('with `--verbose`', () => {
test('prints verbose output for a valid basic project', async () => {
let code = stripIndent`
import '@glint/environment-ember-template-imports';
import Component from '@glimmer/component';
type ApplicationArgs = {
version: string;
};
export default class Application extends Component<{ Args: ApplicationArgs }> {
private startupTime = new Date().toISOString();
<template>
Welcome to app v{{@version}}.
The current time is {{this.startupTime}}.
</template>
}
`;

project.write(INPUT_SFC, code);

let checkResult = await project.build({ reject: false, flags: ['--verbose'] });

expect(checkResult.exitCode).toBe(0);
expect(checkResult.stdout).toMatchInlineSnapshot(`
"5:05:42 PM - Projects in this build:
* tsconfig.json
5:05:42 PM - Project 'tsconfig.json' is out of date because output file 'dist/tsconfig.tsbuildinfo' does not exist
5:05:42 PM - Building project '/Users/ckrycho/dev/typed-ember/glint/test-packages/ephemeral/050b3ab021eb4/tsconfig.json'...
"
`);
expect(checkResult.stderr).toEqual('');
});

test('prints verbose output for a project with a basic template type error', async () => {
let code = stripIndent`
import '@glint/environment-ember-template-imports';
import Component from '@glimmer/component';
type ApplicationArgs = {
version: string;
};
const truncate = (length: number, s: string): string =>
s.slice(0, length);
export default class Application extends Component<{ Args: ApplicationArgs }> {
private startupTime = new Date().toISOString();
<template>
Welcome to app v{{@version}}.
The current time is {{truncate this.startupTime 12}}.
</template>
}
`;

project.write(INPUT_SFC, code);

let checkResult = await project.build({ reject: false, flags: ['--verbose'] });

expect(checkResult.exitCode).toBe(1);
expect(checkResult.stdout).toMatchInlineSnapshot(`
"5:06:23 PM - Projects in this build:
* tsconfig.json
5:06:23 PM - Project 'tsconfig.json' is out of date because output file 'dist/tsconfig.tsbuildinfo' does not exist
5:06:23 PM - Building project '/Users/ckrycho/dev/typed-ember/glint/test-packages/ephemeral/4039021e6fc86/tsconfig.json'...
"
`);
expect(stripAnsi(checkResult.stderr)).toMatchInlineSnapshot(`
"src/index.gts:16:36 - error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
16 The current time is {{truncate this.startupTime 12}}.
~~~~~~~~~~~~~~~~
"
`);
});
});
});

describe('composite projects', () => {
Expand Down Expand Up @@ -1067,6 +1150,98 @@ describe('CLI: single-pass build mode typechecking', () => {
});
});
});

describe('with `--verbose`', () => {
test('for a valid composite subproject with a reference', async () => {
let checkResult = await projects.children.a.build({ reject: false, flags: ['--verbose'] });

expect(checkResult.stdout).toMatchInlineSnapshot(`
"8:47:43 AM - Projects in this build:
* ../c/tsconfig.json
* tsconfig.json
8:47:43 AM - Project '../c/tsconfig.json' is out of date because output file '../c/tsconfig.tsbuildinfo' does not exist
8:47:43 AM - Building project '/Users/ckrycho/dev/typed-ember/glint/test-packages/ephemeral/9c9b34b0f5557/c/tsconfig.json'...
8:47:44 AM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
8:47:44 AM - Building project '/Users/ckrycho/dev/typed-ember/glint/test-packages/ephemeral/9c9b34b0f5557/a/tsconfig.json'...
"
`);
});

test('for a project transitively referenced by the root with a template type error, built from the main project', async () => {
let rootCode = stripIndent`
import Component from '@glimmer/component';
import A from '@glint-test/a';
import B from '@glint-test/b';
type ApplicationArgs = {
version: string;
};
export default class Application extends Component<{ Args: ApplicationArgs }> {
private startupTime = new Date().toISOString();
<template>
Welcome to app v{{@version}}.
The current time is {{this.startupTime}}.
</template>
}
`;

let aCode = stripIndent`
import C from '@glint-test/c';
const A = 'hello ' + C;
export default A;
`;

let bCode = stripIndent`
const B = 'ahoy';
export default B;
`;

let cCode = stripIndent`
const double = (n: number) => n * 2;
const useDouble = <template>{{double "hello"}}</template>;
const C = 'world';
export default C;
`;

projects.main.write(INPUT_SFC, rootCode);
projects.children.a.write(INPUT_SFC, aCode);
projects.children.b.write(INPUT_SFC, bCode);
projects.children.c.write(INPUT_SFC, cCode);

let checkResult = await projects.main.build({ reject: false, flags: ['--verbose'] });

expect(checkResult.stdout).toMatchInlineSnapshot(`
"8:49:55 AM - Projects in this build:
* ../c/tsconfig.json
* ../a/tsconfig.json
* ../b/tsconfig.json
* tsconfig.json
8:49:55 AM - Project '../c/tsconfig.json' is out of date because output file '../c/tsconfig.tsbuildinfo' does not exist
8:49:55 AM - Building project '/Users/ckrycho/dev/typed-ember/glint/test-packages/ephemeral/7d5585b51d249/c/tsconfig.json'...
8:49:56 AM - Project '../a/tsconfig.json' can't be built because its dependency '../c' has errors
8:49:56 AM - Skipping build of project '/Users/ckrycho/dev/typed-ember/glint/test-packages/ephemeral/7d5585b51d249/a/tsconfig.json' because its dependency '/Users/ckrycho/dev/typed-ember/glint/test-packages/ephemeral/7d5585b51d249/c' has errors
8:49:56 AM - Project '../b/tsconfig.json' is out of date because output file '../b/tsconfig.tsbuildinfo' does not exist
8:49:56 AM - Building project '/Users/ckrycho/dev/typed-ember/glint/test-packages/ephemeral/7d5585b51d249/b/tsconfig.json'...
8:49:56 AM - Project 'tsconfig.json' can't be built because its dependency '../a' was not built
8:49:56 AM - Skipping build of project '/Users/ckrycho/dev/typed-ember/glint/test-packages/ephemeral/7d5585b51d249/main/tsconfig.json' because its dependency '/Users/ckrycho/dev/typed-ember/glint/test-packages/ephemeral/7d5585b51d249/a' was not built
"
`);
});
});
});
});

Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ const argv = yargs(process.argv.slice(2))
description: `Show what would be built (or deleted, if specified with '--clean'). Same as the TS \`--dry\` flag.`,
type: 'boolean',
})
.option('verbose', {
implies: 'build',
description:
'Prints out verbose logging to explain what’s going on (may be combined with any other flag). Same as the TS `--verbose` flag.',
type: 'boolean',
})
.option('incremental', {
description:
'Save .tsbuildinfo files to allow for incremental compilation of projects. Same as the TS `--incremental` flag.',
Expand Down Expand Up @@ -87,6 +93,7 @@ if (argv.build) {
clean: argv.clean,
force: argv.force,
dry: argv.dry,
verbose: argv.verbose,
};

if ('incremental' in argv) {
Expand Down

0 comments on commit ba0b3ee

Please sign in to comment.