http-client-java, corner case of client without op or group (#4358)

Found when trying to write subclass as 
```ts
@client({
  name: "ContosoClient",
  service: Cadl.ContosoServer,
})
namespace Cadl.ContosoServer {
  @client({
    name: "ContosoSubClient",
    service: Cadl.ContosoServer,
  })
  namespace SubClient {
    @client({
      name: "ContosoSubSubClient",
      service: Cadl.ContosoServer,
    })
    @route("/contoso/")
    interface ServerOp {
      get(@path(#{ allowReserved: true }) group: string): OkResponse | NoContentResponse;
    }
  }
}
```

<-- this likely not the correct way to write subclient (as Client be
very different from subclient from nested namespace), but at least
emitter should not throw

After this PR, above tsp would result in `ContosoSubSubClient` client,
as this is the only one containing operation.
This commit is contained in:
Weidong Xu 2024-09-10 12:26:01 +08:00 коммит произвёл GitHub
Родитель 5a55338def
Коммит 27c263ee68
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
5 изменённых файлов: 37 добавлений и 13 удалений

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

@ -199,13 +199,12 @@ export class CodeModelBuilder {
} }
const service = listServices(this.program)[0]; const service = listServices(this.program)[0];
const serviceNamespace = service.type; if (!service) {
if (serviceNamespace === undefined) { throw Error("TypeSpec for HTTP must define a service.");
throw Error("Cannot emit yaml for a namespace that doesn't exist.");
} }
this.serviceNamespace = serviceNamespace; this.serviceNamespace = service.type;
this.namespace = getNamespaceFullName(serviceNamespace) || "Azure.Client"; this.namespace = getNamespaceFullName(this.serviceNamespace) || "Azure.Client";
// java namespace // java namespace
const javaNamespace = this.getJavaNamespace(this.namespace); const javaNamespace = this.getJavaNamespace(this.namespace);
@ -219,9 +218,9 @@ export class CodeModelBuilder {
}; };
// init code model // init code model
const title = this.options["service-name"] ?? serviceNamespace.name; const title = this.options["service-name"] ?? this.serviceNamespace.name;
const description = this.getDoc(serviceNamespace); const description = this.getDoc(this.serviceNamespace);
this.codeModel = new CodeModel(title, false, { this.codeModel = new CodeModel(title, false, {
info: { info: {
description: description, description: description,
@ -230,7 +229,7 @@ export class CodeModelBuilder {
default: { default: {
name: title, name: title,
description: description, description: description,
summary: this.getSummary(serviceNamespace), summary: this.getSummary(this.serviceNamespace),
namespace: this.namespace, namespace: this.namespace,
}, },
java: { java: {

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

@ -192,9 +192,11 @@ public class ClientMapper implements IMapper<CodeModel, Client> {
} else { } else {
// service client // service client
ServiceClient serviceClient = Mappers.getServiceClientMapper().map(codeModel); ServiceClient serviceClient = Mappers.getServiceClientMapper().map(codeModel);
builder.serviceClient(serviceClient); if (serviceClient != null) {
builder.serviceClient(serviceClient);
serviceClientsMap.put(serviceClient, codeModel); serviceClientsMap.put(serviceClient, codeModel);
}
} }
} }

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

@ -54,9 +54,16 @@ public class Transformer {
markFlattenedSchemas(codeModel); markFlattenedSchemas(codeModel);
} }
transformOperationGroups(codeModel.getOperationGroups(), codeModel); transformOperationGroups(codeModel.getOperationGroups(), codeModel);
if (codeModel.getGlobalParameters() != null) {
for (Parameter parameter : codeModel.getGlobalParameters()) {
if (parameter.getLanguage().getJava() == null) {
renameVariable(parameter);
}
}
}
// multi-clients for TypeSpec // multi-clients for TypeSpec
if (codeModel.getClients() != null) { if (codeModel.getClients() != null) {
transformClients(codeModel.getClients(), codeModel); transformClients(codeModel.getClients());
} }
return codeModel; return codeModel;
} }
@ -108,7 +115,7 @@ public class Transformer {
} }
} }
private void transformClients(List<Client> clients, CodeModel codeModel) { private void transformClients(List<Client> clients) {
for (Client client : clients) { for (Client client : clients) {
renameClient(client); renameClient(client);
@ -138,6 +145,14 @@ public class Transformer {
} }
} }
} }
if (client.getGlobalParameters() != null) {
for (Parameter parameter : client.getGlobalParameters()) {
if (parameter.getLanguage().getJava() == null) {
renameVariable(parameter);
}
}
}
} }
} }

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

@ -35,7 +35,10 @@ public class TypeSpecClientMapper extends ClientMapper {
Map<ServiceClient, Client> serviceClientsMap = new LinkedHashMap<>(); Map<ServiceClient, Client> serviceClientsMap = new LinkedHashMap<>();
TypeSpecServiceClientMapper mapper = new TypeSpecServiceClientMapper(); TypeSpecServiceClientMapper mapper = new TypeSpecServiceClientMapper();
for (Client client : clients) { for (Client client : clients) {
serviceClientsMap.put(mapper.map(client, codeModel), client); ServiceClient serviceClient = mapper.map(client, codeModel);
if (serviceClient != null) {
serviceClientsMap.put(serviceClient, client);
}
} }
return serviceClientsMap; return serviceClientsMap;
} }

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

@ -55,6 +55,11 @@ public class TypeSpecServiceClientMapper extends ServiceClientMapper {
.forEach(og -> methodGroupClients.add(Mappers.getMethodGroupMapper().map(og, properties))); .forEach(og -> methodGroupClients.add(Mappers.getMethodGroupMapper().map(og, properties)));
builder.methodGroupClients(methodGroupClients); builder.methodGroupClients(methodGroupClients);
if (proxy == null && CoreUtils.isNullOrEmpty(methodGroupClients)) {
// No operation in this client, and no operation group as well. Abort the processing.
return null;
}
if (proxy == null) { if (proxy == null) {
proxy = methodGroupClients.iterator().next().getProxy(); proxy = methodGroupClients.iterator().next().getProxy();
} }