Support Type Alias Scope Expand Detection (#9283)

* add type alias scope extend case

* update version

* update dep
This commit is contained in:
Wanpeng Li 2024-10-30 15:23:55 +08:00 коммит произвёл GitHub
Родитель dfc24b6def
Коммит 16826b8ebc
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
9 изменённых файлов: 38 добавлений и 18 удалений

12
tools/js-sdk-release-tools/package-lock.json сгенерированный
Просмотреть файл

@ -1,12 +1,12 @@
{ {
"name": "@azure-tools/js-sdk-release-tools", "name": "@azure-tools/js-sdk-release-tools",
"version": "2.7.15", "version": "2.7.16",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@azure-tools/js-sdk-release-tools", "name": "@azure-tools/js-sdk-release-tools",
"version": "2.7.15", "version": "2.7.16",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@azure-tools/openapi-tools-common": "^1.2.2", "@azure-tools/openapi-tools-common": "^1.2.2",
@ -25,7 +25,7 @@
"simple-git": "^3.5.0", "simple-git": "^3.5.0",
"ts-morph": "^23.0.0", "ts-morph": "^23.0.0",
"tslib": "^1.9.3", "tslib": "^1.9.3",
"typescript-codegen-breaking-change-detector": "0.5.4", "typescript-codegen-breaking-change-detector": "0.5.5",
"unixify": "^1.0.0", "unixify": "^1.0.0",
"winston": "^3.13.1", "winston": "^3.13.1",
"yaml": "^1.10.2" "yaml": "^1.10.2"
@ -4949,9 +4949,9 @@
} }
}, },
"node_modules/typescript-codegen-breaking-change-detector": { "node_modules/typescript-codegen-breaking-change-detector": {
"version": "0.5.4", "version": "0.5.5",
"resolved": "https://registry.npmjs.org/typescript-codegen-breaking-change-detector/-/typescript-codegen-breaking-change-detector-0.5.4.tgz", "resolved": "https://registry.npmjs.org/typescript-codegen-breaking-change-detector/-/typescript-codegen-breaking-change-detector-0.5.5.tgz",
"integrity": "sha512-75TbgtbpdLX4xlFSBigLB/68WTqwAKAlI62SKrJqhtkDSmkFgeop4EoGbtvAkWq/cAAFqNaeYUQUGCYC8gfhcw==", "integrity": "sha512-tbIKoda+z9AGDuSDwOwnqRu84Ew2H9vLL8zwgN+pAF4DFH+MrwK64Cm1Nt1QrgRhJAGfCK97HxYiaA2pxWjgZQ==",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "^7.17.0", "@typescript-eslint/scope-manager": "^7.17.0",
"@typescript-eslint/types": "^7.17.0", "@typescript-eslint/types": "^7.17.0",

Просмотреть файл

@ -1,6 +1,6 @@
{ {
"name": "@azure-tools/js-sdk-release-tools", "name": "@azure-tools/js-sdk-release-tools",
"version": "2.7.15", "version": "2.7.16",
"description": "", "description": "",
"files": [ "files": [
"dist" "dist"
@ -41,7 +41,7 @@
"simple-git": "^3.5.0", "simple-git": "^3.5.0",
"ts-morph": "^23.0.0", "ts-morph": "^23.0.0",
"tslib": "^1.9.3", "tslib": "^1.9.3",
"typescript-codegen-breaking-change-detector": "0.5.4", "typescript-codegen-breaking-change-detector": "0.5.5",
"unixify": "^1.0.0", "unixify": "^1.0.0",
"winston": "^3.13.1", "winston": "^3.13.1",
"yaml": "^1.10.2" "yaml": "^1.10.2"

Просмотреть файл

@ -16,6 +16,9 @@ export interface Routes {
export type typesChange = "basic" | "remove"; export type typesChange = "basic" | "remove";
export type typesRemove = "basic" | "remove"; export type typesRemove = "basic" | "remove";
export type typesExpand = string | number;
export type typesNarrow = string | number | boolean;
export interface A {a: string;} export interface A {a: string;}
export interface B {b: string;} export interface B {b: string;}
export interface C {c: string;} export interface C {c: string;}

Просмотреть файл

@ -20,6 +20,9 @@ export interface Routes {
export type typesChange = "basic" | "rEmove"; export type typesChange = "basic" | "rEmove";
export type typesAdd = "basic" | "rEmove"; export type typesAdd = "basic" | "rEmove";
export type typesExpand = string | number | boolean;
export type typesNarrow = string | number;
export interface A {a: string;} export interface A {a: string;}
export interface B {b: string;} export interface B {b: string;}
export interface C {c: string;} export interface C {c: string;}

Просмотреть файл

@ -1,6 +1,6 @@
{ {
"name": "typescript-codegen-breaking-change-detector", "name": "typescript-codegen-breaking-change-detector",
"version": "0.5.4", "version": "0.5.5",
"description": "Detect breaking changes to your TypeScript client generated by open api, typespec and more...", "description": "Detect breaking changes to your TypeScript client generated by open api, typespec and more...",
"main": "dist/src/index.js", "main": "dist/src/index.js",
"types": "./dist/src/index.d.ts", "types": "./dist/src/index.d.ts",

Просмотреть файл

@ -376,7 +376,7 @@ export function findFunctionBreakingChanges(source: FunctionDeclaration, target:
} }
export function findTypeAliasBreakingChanges(source: TypeAliasDeclaration, target: TypeAliasDeclaration): DiffPair[] { export function findTypeAliasBreakingChanges(source: TypeAliasDeclaration, target: TypeAliasDeclaration): DiffPair[] {
if (source.getType().isAssignableTo(target.getType())) return []; if (source.getType().isAssignableTo(target.getType()) && target.getType().isAssignableTo(source.getType())) return [];
let sourceNameNode: NameNode = { name: source.getName(), node: source }; let sourceNameNode: NameNode = { name: source.getName(), node: source };
let targetNameNode: NameNode = { name: target.getName(), node: target }; let targetNameNode: NameNode = { name: target.getName(), node: target };

Просмотреть файл

@ -74,7 +74,7 @@ export function patchRoutes(astContext: AstContext): DiffPair[] {
return [...breakingChangePairs, ...newFeaturePairs]; return [...breakingChangePairs, ...newFeaturePairs];
} }
export function patchUnionType(name: string, astContext: AstContext, assignDirection: AssignDirection): DiffPair[] { export function patchTypeAlias(name: string, astContext: AstContext, assignDirection: AssignDirection): DiffPair[] {
const baseline = astContext.baseline.getTypeAlias(name); const baseline = astContext.baseline.getTypeAlias(name);
const current = astContext.current.getTypeAlias(name); const current = astContext.current.getTypeAlias(name);

Просмотреть файл

@ -3,7 +3,7 @@ import { describe, expect, test } from 'vitest';
import { join } from 'node:path'; import { join } from 'node:path';
import { createAstContext } from '../azure/detect-breaking-changes'; import { createAstContext } from '../azure/detect-breaking-changes';
import { patchFunction, patchRoutes, patchUnionType } from '../azure/patch/patch-detection'; import { patchFunction, patchRoutes, patchTypeAlias } from '../azure/patch/patch-detection';
import { createTempFolder, getFormattedDate } from './utils'; import { createTempFolder, getFormattedDate } from './utils';
import { DiffLocation, DiffReasons, AssignDirection } from '../azure/common/types'; import { DiffLocation, DiffReasons, AssignDirection } from '../azure/common/types';
@ -142,26 +142,40 @@ describe("patch current tool's breaking changes", async () => {
try { try {
const tempFolder = await createTempFolder(`.tmp/temp-${date}`); const tempFolder = await createTempFolder(`.tmp/temp-${date}`);
const astContext = await createAstContext(baselineApiViewPath, currentApiViewPath, tempFolder); const astContext = await createAstContext(baselineApiViewPath, currentApiViewPath, tempFolder);
let breakingPairs = patchUnionType('typesChange', astContext, AssignDirection.CurrentToBaseline); let breakingPairs = patchTypeAlias('typesChange', astContext, AssignDirection.CurrentToBaseline);
expect(breakingPairs.length).toBe(1); expect(breakingPairs.length).toBe(1);
expect(breakingPairs[0].assignDirection).toBe(AssignDirection.CurrentToBaseline); expect(breakingPairs[0].assignDirection).toBe(AssignDirection.CurrentToBaseline);
expect(breakingPairs[0].location).toBe(DiffLocation.TypeAlias); expect(breakingPairs[0].location).toBe(DiffLocation.TypeAlias);
expect(breakingPairs[0].reasons).toBe(DiffReasons.TypeChanged); expect(breakingPairs[0].reasons).toBe(DiffReasons.TypeChanged);
expect(breakingPairs[0].target?.name).toBe('typesChange'); expect(breakingPairs[0].target?.name).toBe('typesChange');
breakingPairs = patchUnionType('typesRemove', astContext, AssignDirection.CurrentToBaseline); breakingPairs = patchTypeAlias('typesRemove', astContext, AssignDirection.CurrentToBaseline);
expect(breakingPairs.length).toBe(1); expect(breakingPairs.length).toBe(1);
expect(breakingPairs[0].assignDirection).toBe(AssignDirection.CurrentToBaseline); expect(breakingPairs[0].assignDirection).toBe(AssignDirection.CurrentToBaseline);
expect(breakingPairs[0].location).toBe(DiffLocation.TypeAlias); expect(breakingPairs[0].location).toBe(DiffLocation.TypeAlias);
expect(breakingPairs[0].reasons).toBe(DiffReasons.Removed); expect(breakingPairs[0].reasons).toBe(DiffReasons.Removed);
expect(breakingPairs[0].target?.name).toBe('typesRemove'); expect(breakingPairs[0].target?.name).toBe('typesRemove');
breakingPairs = patchUnionType('typesAdd', astContext, AssignDirection.CurrentToBaseline); breakingPairs = patchTypeAlias('typesAdd', astContext, AssignDirection.CurrentToBaseline);
expect(breakingPairs.length).toBe(1); expect(breakingPairs.length).toBe(1);
expect(breakingPairs[0].assignDirection).toBe(AssignDirection.CurrentToBaseline); expect(breakingPairs[0].assignDirection).toBe(AssignDirection.CurrentToBaseline);
expect(breakingPairs[0].location).toBe(DiffLocation.TypeAlias); expect(breakingPairs[0].location).toBe(DiffLocation.TypeAlias);
expect(breakingPairs[0].reasons).toBe(DiffReasons.Added); expect(breakingPairs[0].reasons).toBe(DiffReasons.Added);
expect(breakingPairs[0].source?.name).toBe('typesAdd'); expect(breakingPairs[0].source?.name).toBe('typesAdd');
breakingPairs = patchTypeAlias('typesExpand', astContext, AssignDirection.CurrentToBaseline);
expect(breakingPairs.length).toBe(1);
expect(breakingPairs[0].assignDirection).toBe(AssignDirection.CurrentToBaseline);
expect(breakingPairs[0].location).toBe(DiffLocation.TypeAlias);
expect(breakingPairs[0].reasons).toBe(DiffReasons.TypeChanged);
expect(breakingPairs[0].source?.name).toBe('typesExpand');
breakingPairs = patchTypeAlias('typesNarrow', astContext, AssignDirection.CurrentToBaseline);
expect(breakingPairs.length).toBe(1);
expect(breakingPairs[0].assignDirection).toBe(AssignDirection.CurrentToBaseline);
expect(breakingPairs[0].location).toBe(DiffLocation.TypeAlias);
expect(breakingPairs[0].reasons).toBe(DiffReasons.TypeChanged);
expect(breakingPairs[0].source?.name).toBe('typesNarrow');
} finally { } finally {
if (tempFolder) remove(tempFolder); if (tempFolder) remove(tempFolder);
} }

Просмотреть файл

@ -15,7 +15,7 @@ import {
RuleMessageKind, RuleMessageKind,
detectBreakingChangesBetweenPackages, detectBreakingChangesBetweenPackages,
patchRoutes, patchRoutes,
patchUnionType, patchTypeAlias,
patchFunction, patchFunction,
} from "typescript-codegen-breaking-change-detector"; } from "typescript-codegen-breaking-change-detector";
@ -1223,7 +1223,7 @@ export const changelogGenerator = (
const typeAliasNames = new Set([...Object.keys(metaDataOld.typeAlias), ...Object.keys(metadataNew.typeAlias)]); const typeAliasNames = new Set([...Object.keys(metaDataOld.typeAlias), ...Object.keys(metadataNew.typeAlias)]);
const typeAliasPairs = [...typeAliasNames].reduce((pairs, typeAliasName) => { const typeAliasPairs = [...typeAliasNames].reduce((pairs, typeAliasName) => {
pairs.push(...patchUnionType(typeAliasName, astContext, AssignDirection.CurrentToBaseline)); pairs.push(...patchTypeAlias(typeAliasName, astContext, AssignDirection.CurrentToBaseline));
return pairs; return pairs;
}, new Array<DiffPair>()); }, new Array<DiffPair>());
handleAddedRemovedTypeAliasDiffPairs(typeAliasPairs, changLog); handleAddedRemovedTypeAliasDiffPairs(typeAliasPairs, changLog);
@ -1231,7 +1231,7 @@ export const changelogGenerator = (
// NOTE: handle type alias's type change case in simple way for now, and exclude intersection type, since already handled // NOTE: handle type alias's type change case in simple way for now, and exclude intersection type, since already handled
// TODO: handle type alias's type change case in a general way // TODO: handle type alias's type change case in a general way
const typeAliasPairsReverse = [...typeAliasNames].reduce((pairs, typeAliasName) => { const typeAliasPairsReverse = [...typeAliasNames].reduce((pairs, typeAliasName) => {
pairs.push(...patchUnionType(typeAliasName, astContext, AssignDirection.BaselineToCurrent)); pairs.push(...patchTypeAlias(typeAliasName, astContext, AssignDirection.BaselineToCurrent));
return pairs; return pairs;
}, new Array<DiffPair>()); }, new Array<DiffPair>());