From f21484e71763ca09c0a17b65ec191f9e2d150d4e Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Wed, 11 Dec 2024 14:13:50 +0800 Subject: [PATCH 1/2] bump TCGC version to 0.48.4 (#5260) Fixes https://github.com/microsoft/typespec/issues/5261 --- .../emitter/src/lib/operation-converter.ts | 2 +- .../http-client-csharp/emitter/test/Unit/usage.test.ts | 3 ++- .../src/InputTypes/InputModelTypeUsage.cs | 4 +++- .../http/authentication/api-key/tspCodeModel.json | 2 +- .../http/authentication/http/custom/tspCodeModel.json | 2 +- .../http/authentication/oauth2/tspCodeModel.json | 2 +- packages/http-client-csharp/package-lock.json | 8 ++++---- packages/http-client-csharp/package.json | 2 +- 8 files changed, 14 insertions(+), 11 deletions(-) diff --git a/packages/http-client-csharp/emitter/src/lib/operation-converter.ts b/packages/http-client-csharp/emitter/src/lib/operation-converter.ts index dfe8cecdb7..ce895e80be 100644 --- a/packages/http-client-csharp/emitter/src/lib/operation-converter.ts +++ b/packages/http-client-csharp/emitter/src/lib/operation-converter.ts @@ -319,7 +319,7 @@ function getMediaTypes(type: SdkType): string[] { function loadOperationPaging( method: SdkServiceMethod, ): OperationPaging | undefined { - if (method.kind !== "paging") { + if (method.kind !== "paging" || method.__raw_paged_metadata === undefined) { return undefined; } diff --git a/packages/http-client-csharp/emitter/test/Unit/usage.test.ts b/packages/http-client-csharp/emitter/test/Unit/usage.test.ts index c6aef747a0..42e5899f49 100644 --- a/packages/http-client-csharp/emitter/test/Unit/usage.test.ts +++ b/packages/http-client-csharp/emitter/test/Unit/usage.test.ts @@ -664,6 +664,7 @@ interface LegacyLro { ); ok(radiologyInsightsInferenceResult); - strictEqual(radiologyInsightsInferenceResult.usage, UsageFlags.Output | UsageFlags.Json); + // TODO -- TCGC now has a bug that the LRO final result does not have Json usage when the polling operation does not have convenientAPI but the LRO has convenientAPI. https://github.com/Azure/typespec-azure/issues/1964 + //strictEqual(radiologyInsightsInferenceResult.usage, UsageFlags.Output | UsageFlags.Json); }); }); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.Input/src/InputTypes/InputModelTypeUsage.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.Input/src/InputTypes/InputModelTypeUsage.cs index 12fd1d6eb0..86ae8864fb 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.Input/src/InputTypes/InputModelTypeUsage.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.Input/src/InputTypes/InputModelTypeUsage.cs @@ -16,6 +16,8 @@ public enum InputModelTypeUsage MultipartFormData = 32, Spread = 64, Error = 128, - Json = 256 + Json = 256, + Xml = 512, + Exception = 1024, } } diff --git a/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/api-key/tspCodeModel.json b/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/api-key/tspCodeModel.json index fc72c08e84..e482e7e3f6 100644 --- a/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/api-key/tspCodeModel.json +++ b/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/api-key/tspCodeModel.json @@ -9,7 +9,7 @@ "kind": "model", "name": "InvalidAuth", "crossLanguageDefinitionId": "Authentication.ApiKey.InvalidAuth", - "usage": "Output,Error,Json", + "usage": "Error,Json,Exception", "decorators": [], "properties": [ { diff --git a/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/http/custom/tspCodeModel.json b/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/http/custom/tspCodeModel.json index 3cb9614684..d3581f4452 100644 --- a/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/http/custom/tspCodeModel.json +++ b/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/http/custom/tspCodeModel.json @@ -9,7 +9,7 @@ "kind": "model", "name": "InvalidAuth", "crossLanguageDefinitionId": "Authentication.Http.Custom.InvalidAuth", - "usage": "Output,Error,Json", + "usage": "Error,Json,Exception", "decorators": [], "properties": [ { diff --git a/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/oauth2/tspCodeModel.json b/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/oauth2/tspCodeModel.json index f6950afdf7..58548e8802 100644 --- a/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/oauth2/tspCodeModel.json +++ b/packages/http-client-csharp/generator/TestProjects/CadlRanch/http/authentication/oauth2/tspCodeModel.json @@ -9,7 +9,7 @@ "kind": "model", "name": "InvalidAuth", "crossLanguageDefinitionId": "Authentication.OAuth2.InvalidAuth", - "usage": "Output,Error,Json", + "usage": "Error,Json,Exception", "decorators": [], "properties": [ { diff --git a/packages/http-client-csharp/package-lock.json b/packages/http-client-csharp/package-lock.json index 367625b668..7d35c77562 100644 --- a/packages/http-client-csharp/package-lock.json +++ b/packages/http-client-csharp/package-lock.json @@ -15,7 +15,7 @@ "@azure-tools/cadl-ranch": "0.16.1", "@azure-tools/cadl-ranch-specs": "0.39.3", "@azure-tools/typespec-azure-core": "0.48.0", - "@azure-tools/typespec-client-generator-core": "0.48.1", + "@azure-tools/typespec-client-generator-core": "0.48.4", "@microsoft/api-extractor": "^7.47.11", "@types/node": "~22.7.5", "@typespec/compiler": "0.62.0", @@ -215,9 +215,9 @@ } }, "node_modules/@azure-tools/typespec-client-generator-core": { - "version": "0.48.1", - "resolved": "https://registry.npmjs.org/@azure-tools/typespec-client-generator-core/-/typespec-client-generator-core-0.48.1.tgz", - "integrity": "sha512-pYEZDExltNNLAaA12EwEag5VLESyPoKNQQ/6Olj4rJouA4cBjZDTW80VYgKuPQBt/uCtA0Yn6xxl0nH7TGOwWQ==", + "version": "0.48.4", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-client-generator-core/-/typespec-client-generator-core-0.48.4.tgz", + "integrity": "sha512-TvX84FiQ3rax0e838m6kpVj8F24OzKAbyLgUXXZ/TjfxhvZb1u0ojMjSKAvmcal2klROJqRlj4d9tImidPYpgA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/packages/http-client-csharp/package.json b/packages/http-client-csharp/package.json index 0288ea2c50..39d2a2a9d8 100644 --- a/packages/http-client-csharp/package.json +++ b/packages/http-client-csharp/package.json @@ -58,7 +58,7 @@ "@azure-tools/cadl-ranch": "0.16.1", "@azure-tools/cadl-ranch-specs": "0.39.3", "@azure-tools/typespec-azure-core": "0.48.0", - "@azure-tools/typespec-client-generator-core": "0.48.1", + "@azure-tools/typespec-client-generator-core": "0.48.4", "@microsoft/api-extractor": "^7.47.11", "@types/node": "~22.7.5", "@typespec/compiler": "0.62.0", From a862ac7f18e66b1d93c9870bd8e50ad77b2ee07e Mon Sep 17 00:00:00 2001 From: Xiaofei Cao <92354331+XiaofeiCao@users.noreply.github.com> Date: Wed, 11 Dec 2024 14:49:39 +0800 Subject: [PATCH 2/2] http-client-java, fix eclipse languageserver when tmp folder is corrupted (#5307) ### Situation I somehow encountered a folder corruption situation that the tmp folder for language server is there, but with no Jar file. Language server didn't start correctly, but the exception is thrown only when JSON RPC to the server is performed. Screenshot 2024-12-11 at 14 23 52 ### This PR - In case the language server did not start correctly, and user did not explicitly provide a language server path, force a re-download. - If the server failed to start anyway, throw with the process output. ### Test #### Normal first download Screenshot 2024-12-09 at 20 12 06 #### Normal downloaded Screenshot 2024-12-09 at 20 09 22 #### Corrupted folder, we do a re-download Screenshot 2024-12-09 at 20 08 35 #### Server failed to start anyway, we throw with server output Screenshot 2024-12-10 at 16 48 25 --- .../ls/EclipseLanguageServerFacade.java | 69 +++++++++++++++---- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/customization/implementation/ls/EclipseLanguageServerFacade.java b/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/customization/implementation/ls/EclipseLanguageServerFacade.java index 04c37587f1..8e151d13a3 100644 --- a/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/customization/implementation/ls/EclipseLanguageServerFacade.java +++ b/packages/http-client-java/generator/http-client-generator-core/src/main/java/com/microsoft/typespec/http/client/generator/core/customization/implementation/ls/EclipseLanguageServerFacade.java @@ -4,8 +4,10 @@ package com.microsoft.typespec.http.client.generator.core.customization.implementation.ls; import com.microsoft.typespec.http.client.generator.core.customization.implementation.Utils; +import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UncheckedIOException; import java.net.URI; @@ -16,6 +18,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.zip.GZIPInputStream; import org.apache.tools.tar.TarEntry; import org.apache.tools.tar.TarInputStream; @@ -33,7 +36,7 @@ public EclipseLanguageServerFacade(String pathToLanguageServerPlugin, Logger log int javaVersion = Runtime.version().feature(); Path languageServerPath = (pathToLanguageServerPlugin == null) - ? getLanguageServerDirectory(javaVersion, logger) + ? getLanguageServerDirectory(javaVersion, logger, false) : Paths.get(pathToLanguageServerPlugin).resolve("jdt-language-server"); List command = new ArrayList<>(); @@ -71,18 +74,55 @@ public EclipseLanguageServerFacade(String pathToLanguageServerPlugin, Logger log command.add("./config_linux"); } - logger.info("Starting Eclipse JDT language server at {}", languageServerPath); - server = new ProcessBuilder(command).redirectOutput(ProcessBuilder.Redirect.PIPE) - .redirectInput(ProcessBuilder.Redirect.PIPE) - .redirectErrorStream(true) - .directory(languageServerPath.toFile()) - .start(); + Process server = startServer(command, languageServerPath, logger); + if (!server.isAlive()) { + if (pathToLanguageServerPlugin == null) { + // If user didn't specify language server path, we do a clean re-download. + logger + .warn("Eclipse language server failed to start. The folder may be corrupted. Try re-download."); + server = startServer(command, getLanguageServerDirectory(javaVersion, logger, true), logger); + if (!server.isAlive()) { + // if server failed to start anyway, throw with server output. + throw new RuntimeException(String.format( + "Eclipse language server failed to start, error output:\n %s", readServerOutput(server))); + } + } else { + // if user specify the language server path, we just throw with server output. + throw new RuntimeException(String.format( + "Eclipse language server failed to start, error output:\n %s", readServerOutput(server))); + } + } + this.server = server; } catch (Exception e) { throw new RuntimeException(e); } } - private static Path getLanguageServerDirectory(int javaVersion, Logger logger) throws IOException { + private String readServerOutput(Process server) throws IOException { + if (server.getInputStream() == null) { + return null; + } + StringBuilder stringBuilder = new StringBuilder(); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(server.getInputStream()))) { + reader.lines().forEachOrdered(line -> stringBuilder.append(line).append("\n")); + } + return stringBuilder.toString(); + } + + private Process startServer(List command, Path languageServerPath, Logger logger) throws Exception { + logger.info("Starting Eclipse JDT language server at {}", languageServerPath); + final Process server; + server = new ProcessBuilder(command).redirectOutput(ProcessBuilder.Redirect.PIPE) + .redirectInput(ProcessBuilder.Redirect.PIPE) + .redirectErrorStream(true) + .directory(languageServerPath.toFile()) + .start(); + server.waitFor(1, TimeUnit.SECONDS); + return server; + } + + private static Path getLanguageServerDirectory(int javaVersion, Logger logger, boolean forceReDownload) + throws IOException { Path tmp = Paths.get(System.getProperty("java.io.tmpdir")); Path autorestLanguageServer = tmp.resolve("autorest-java-language-server"); @@ -104,9 +144,12 @@ private static Path getLanguageServerDirectory(int javaVersion, Logger logger) t } Path languageServer = languageServerPath.resolve("jdt-language-server"); - if (!Files.exists(languageServerPath) || !Files.exists(languageServer)) { - Files.createDirectories(languageServerPath); + + if (!Files.exists(languageServer) || forceReDownload) { + Files.createDirectories(languageServer); Path zipPath = languageServerPath.resolve("jdt-language-server.tar.gz"); + Files.deleteIfExists(zipPath); + logger.info("Downloading Eclipse JDT language server from {} to {}", downloadUrl, zipPath); try (InputStream in = downloadUrl.openStream()) { Files.copy(in, zipPath); @@ -122,13 +165,15 @@ private static Path getLanguageServerDirectory(int javaVersion, Logger logger) t private static Path unzipLanguageServer(Path zipPath) throws IOException { try (TarInputStream tar = new TarInputStream(new GZIPInputStream(Files.newInputStream(zipPath)))) { Path languageServerDirectory = zipPath.getParent().resolve("jdt-language-server"); - Files.createDirectory(languageServerDirectory); TarEntry entry; while ((entry = tar.getNextEntry()) != null) { if (entry.isDirectory()) { Files.createDirectories(languageServerDirectory.resolve(entry.getName())); } else { - Files.copy(tar, languageServerDirectory.resolve(entry.getName())); + Path entryPath = languageServerDirectory.resolve(entry.getName()); + // In case of corrupted folder, delete before create. + Files.deleteIfExists(entryPath); + Files.copy(tar, entryPath); } }