Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 51 additions & 16 deletions packages/angular/cli/src/commands/generate/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ export class GenerateCommandModule
// When 'describe' is set to false, it results in a hidden command.
describe: hidden === true ? false : typeof description === 'string' ? description : '',
deprecated: xDeprecated === true || typeof xDeprecated === 'string' ? xDeprecated : false,
aliases: Array.isArray(aliases) ? (aliases as string[]) : undefined,
aliases: Array.isArray(aliases)
? await this.generateCommandAliasesStrings(collectionName, aliases as string[])
: undefined,
builder: (localYargs) => this.addSchemaOptionsToCommand(localYargs, options).strict(),
handler: (options) =>
this.handler({ ...options, schematic: `${collectionName}:${schematicName}` }),
Expand Down Expand Up @@ -120,6 +122,41 @@ export class GenerateCommandModule
return collectionName ? [collectionName] : [...(await this.getSchematicCollections())];
}

private async shouldAddCollectionNameAsPartOfCommand(): Promise<boolean> {
const [collectionNameFromArgs] = this.parseSchematicInfo(
// positional = [generate, component] or [generate]
this.context.args.positional[1],
);

const schematicCollectionsFromConfig = await this.getSchematicCollections();
const collectionNames = await this.getCollectionNames();

// Only add the collection name as part of the command when it's not a known
// schematics collection or when it has been provided via the CLI.
// Ex:`ng generate @schematics/angular:c`
return (
!!collectionNameFromArgs ||
!collectionNames.some((c) => schematicCollectionsFromConfig.has(c))
);
}

/**
* Generate an aliases string array to be passed to the command builder.
*
* @example `[component]` or `[@schematics/angular:component]`.
*/
private async generateCommandAliasesStrings(
collectionName: string,
schematicAliases: string[],
): Promise<string[]> {
// Only add the collection name as part of the command when it's not a known
// schematics collection or when it has been provided via the CLI.
// Ex:`ng generate @schematics/angular:c`
return (await this.shouldAddCollectionNameAsPartOfCommand())
? schematicAliases.map((alias) => `${collectionName}:${alias}`)
: schematicAliases;
}

/**
* Generate a command string to be passed to the command builder.
*
Expand All @@ -130,23 +167,14 @@ export class GenerateCommandModule
schematicName: string,
options: Option[],
): Promise<string> {
const [collectionNameFromArgs] = this.parseSchematicInfo(
// positional = [generate, component] or [generate]
this.context.args.positional[1],
);

const dasherizedSchematicName = strings.dasherize(schematicName);
const schematicCollectionsFromConfig = await this.getSchematicCollections();
const collectionNames = await this.getCollectionNames();

// Only add the collection name as part of the command when it's not a known
// schematics collection or when it has been provided via the CLI.
// Ex:`ng generate @schematics/angular:component`
const commandName =
!!collectionNameFromArgs ||
!collectionNames.some((c) => schematicCollectionsFromConfig.has(c))
? collectionName + ':' + dasherizedSchematicName
: dasherizedSchematicName;
const commandName = (await this.shouldAddCollectionNameAsPartOfCommand())
? collectionName + ':' + dasherizedSchematicName
: dasherizedSchematicName;

const positionalArgs = options
.filter((o) => o.positional !== undefined)
Expand All @@ -165,6 +193,7 @@ export class GenerateCommandModule
*/
private async *getSchematics(): AsyncGenerator<{
schematicName: string;
schematicAliases?: Set<string>;
collectionName: string;
}> {
const seenNames = new Set<string>();
Expand All @@ -176,7 +205,10 @@ export class GenerateCommandModule
// If a schematic with this same name is already registered skip.
if (!seenNames.has(schematicName)) {
seenNames.add(schematicName);
yield { schematicName, collectionName };
const { aliases } = collection.description.schematics[schematicName];
const schematicAliases = aliases && new Set(aliases);

yield { schematicName, schematicAliases, collectionName };
}
}
}
Expand All @@ -196,8 +228,11 @@ export class GenerateCommandModule
this.context.args.positional[1],
);

for await (const { schematicName, collectionName } of this.getSchematics()) {
if (schematicName === schematicNameFromArgs) {
for await (const { schematicName, collectionName, schematicAliases } of this.getSchematics()) {
if (
schematicNameFromArgs &&
(schematicName === schematicNameFromArgs || schematicAliases?.has(schematicNameFromArgs))
) {
return [[schematicName, collectionName]];
}

Expand Down
14 changes: 14 additions & 0 deletions tests/legacy-cli/e2e/tests/generate/schematic-aliases.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ng } from '../../utils/process';

export default async function () {
const schematicNameVariation = [
'component',
'c',
'@schematics/angular:component',
'@schematics/angular:c',
];

for (const schematic of schematicNameVariation) {
await ng('generate', schematic, 'comp-name', '--display-block', '--dry-run');
}
}