From e2b6d23af36b7d3078367c2c94dbc89ef385dd1c Mon Sep 17 00:00:00 2001 From: Weidong Xu Date: Mon, 11 Nov 2024 17:23:21 +0800 Subject: [PATCH] use namespace from code-model --- .../emitter/src/code-model-builder.ts | 67 ++++++++++++++++--- .../generator/core/mapper/MapperUtils.java | 2 + .../generator/core/mapper/ObjectMapper.java | 2 + 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/packages/http-client-java/emitter/src/code-model-builder.ts b/packages/http-client-java/emitter/src/code-model-builder.ts index 8b019c6e12..9452ae2b06 100644 --- a/packages/http-client-java/emitter/src/code-model-builder.ts +++ b/packages/http-client-java/emitter/src/code-model-builder.ts @@ -168,6 +168,8 @@ export class CodeModelBuilder { private program: Program; private typeNameOptions: TypeNameOptions; private namespace: string; + private baseJavaNamespace: string; + // private legacyJavaNamespace: boolean; private sdkContext!: SdkContext; private options: EmitterOptions; private codeModel: CodeModel; @@ -206,7 +208,8 @@ export class CodeModelBuilder { this.namespace = getNamespaceFullName(this.serviceNamespace) || "Azure.Client"; // java namespace - const javaNamespace = this.getJavaNamespace(this.namespace); + this.baseJavaNamespace = this.getJavaNamespace(this.namespace)!; + // this.legacyJavaNamespace = this.options.namespace != undefined && this.options.namespace.length > 0; const namespace1 = this.namespace; this.typeNameOptions = { @@ -233,7 +236,7 @@ export class CodeModelBuilder { namespace: this.namespace, }, java: { - namespace: javaNamespace, + namespace: this.baseJavaNamespace, }, }, }); @@ -267,6 +270,8 @@ export class CodeModelBuilder { this.processSchemaUsage(); + this.processJavaNamespace(); + this.deduplicateSchemaName(); return this.codeModel; @@ -424,6 +429,16 @@ export class CodeModelBuilder { this.codeModel.schemas.constants?.forEach((it) => this.resolveSchemaUsage(it)); } + private processJavaNamespace() { + // post process for usage and namespace ("implementation.models") + this.codeModel.schemas.objects?.forEach((it) => this.updateJavaNamespace(it)); + this.codeModel.schemas.groups?.forEach((it) => this.updateJavaNamespace(it)); + this.codeModel.schemas.choices?.forEach((it) => this.updateJavaNamespace(it)); + this.codeModel.schemas.sealedChoices?.forEach((it) => this.updateJavaNamespace(it)); + this.codeModel.schemas.ors?.forEach((it) => this.updateJavaNamespace(it)); + this.codeModel.schemas.constants?.forEach((it) => this.updateJavaNamespace(it)); + } + private deduplicateSchemaName() { // deduplicate model name const nameCount = new Map(); @@ -483,6 +498,33 @@ export class CodeModelBuilder { } } + private updateJavaNamespace(schema: Schema) { + if ( + schema instanceof ObjectSchema || + schema instanceof GroupSchema || + schema instanceof ChoiceSchema || + schema instanceof SealedChoiceSchema || + schema instanceof OrSchema || + schema instanceof ConstantSchema + ) { + const schemaUsage: SchemaContext[] | undefined = schema.usage; + + if (schema.language.java?.namespace) { + if (this.isBranded() && schema.language.java.namespace.startsWith("com.azure.")) { + // skip com.azure models + return; + } + + if (schemaUsage?.includes(SchemaContext.Internal)) { + schema.language.java.namespace = schema.language.java.namespace + ".implementation"; + } + if (this.isBranded()) { + schema.language.java.namespace = schema.language.java.namespace + ".models"; + } + } + } + } + private processClients() { // preprocess group-etag-headers this.options["group-etag-headers"] = this.options["group-etag-headers"] ?? true; @@ -490,13 +532,13 @@ export class CodeModelBuilder { const sdkPackage = this.sdkContext.sdkPackage; for (const client of sdkPackage.clients) { let clientName = client.name; - let javaNamespace = this.getJavaNamespace(this.namespace); + let javaNamespace = this.baseJavaNamespace; const clientFullName = client.name; const clientNameSegments = clientFullName.split("."); if (clientNameSegments.length > 1) { clientName = clientNameSegments.at(-1)!; - const clientSubNamespace = clientNameSegments.slice(0, -1).join("."); - javaNamespace = this.getJavaNamespace(this.namespace + "." + clientSubNamespace); + const clientSubNamespace = clientNameSegments.slice(0, -1).join(".").toLowerCase(); + javaNamespace = this.baseJavaNamespace + "." + clientSubNamespace; } const codeModelClient = new CodeModelClient(clientName, client.doc ?? "", { @@ -955,7 +997,7 @@ export class CodeModelBuilder { language: { java: { name: "OperationLocationPollingStrategy", - namespace: this.getJavaNamespace(this.namespace) + ".implementation", + namespace: this.baseJavaNamespace + ".implementation", }, }, }); @@ -2327,8 +2369,8 @@ export class CodeModelBuilder { : this.namespace; return getFileDetailsSchema( property, - getNamespace(property.type.__raw) ?? this.namespace, namespace, + this.getJavaNamespace(namespace), this.codeModel.schemas, this.binarySchema, this.stringSchema, @@ -2447,16 +2489,21 @@ export class CodeModelBuilder { private getJavaNamespace(namespace: string | undefined): string | undefined { const tspNamespace = this.namespace; const baseJavaNamespace = this.emitterContext.options.namespace; + + let javaNamespace; if (!namespace) { - return undefined; + javaNamespace = undefined; } else if ( baseJavaNamespace && (namespace === tspNamespace || namespace.startsWith(tspNamespace + ".")) ) { - return baseJavaNamespace + namespace.slice(tspNamespace.length).toLowerCase(); + // make sure the mapping of typespec service namespace to options.namespace is maintained + // e.g. "Microsoft.StandbyPool" to "com.azure.resourcemanager.standbypool" + javaNamespace = baseJavaNamespace; } else { - return "com." + namespace.toLowerCase(); + javaNamespace = "com." + namespace.toLowerCase(); } + return javaNamespace; } private logWarning(msg: string) { diff --git a/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/mapper/MapperUtils.java b/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/mapper/MapperUtils.java index b625e2fc58..a0b7a96c03 100644 --- a/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/mapper/MapperUtils.java +++ b/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/mapper/MapperUtils.java @@ -61,6 +61,8 @@ public static IType createEnumType(ChoiceSchema enumType, boolean expandable, bo String enumPackage = settings.getPackage(settings.getModelsSubpackage()); if (settings.isCustomType(enumTypeName)) { enumPackage = settings.getPackage(settings.getCustomTypesSubpackage()); + } else if (settings.isDataPlaneClient() && enumType.getLanguage().getJava().getNamespace() != null) { + enumPackage = enumType.getLanguage().getJava().getNamespace(); } else if (settings.isDataPlaneClient() && (enumType.getUsage() != null && enumType.getUsage().contains(SchemaContext.INTERNAL))) { // internal type, which is not exposed to user diff --git a/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/mapper/ObjectMapper.java b/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/mapper/ObjectMapper.java index fb71424648..32c8a7fb59 100644 --- a/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/mapper/ObjectMapper.java +++ b/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/mapper/ObjectMapper.java @@ -54,6 +54,8 @@ private ClassType createClassType(ObjectSchema compositeType) { } else if (settings.isFluent() && compositeType.isFlattenedSchema()) { // put class of flattened type to implementation package classPackage = settings.getPackage(settings.getFluentModelsSubpackage()); + } else if (settings.isDataPlaneClient() && compositeType.getLanguage().getJava().getNamespace() != null) { + classPackage = compositeType.getLanguage().getJava().getNamespace(); } else if (settings.isDataPlaneClient() && isInternalModel(compositeType)) { // internal type is not exposed to user classPackage = settings.getPackage(settings.getImplementationSubpackage(), settings.getModelsSubpackage());