@azure-tools/typespec-java
Version:
TypeSpec library for emitting Java client from the TypeSpec REST protocol binding
167 lines • 7.66 kB
JavaScript
import { getNormalizedAbsolutePath, NoTarget, resolvePath, } from "@typespec/compiler";
import { promises } from "fs";
import { dump } from "js-yaml";
import { dirname } from "path";
import { fileURLToPath } from "url";
import { CodeModelBuilder } from "./code-model-builder.js";
import { LibName, reportDiagnostic } from "./lib.js";
import { DiagnosticError, spawnAsync, SpawnError, trace } from "./utils.js";
import { validateDependencies } from "./validate.js";
export async function $onEmit(context) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
const program = context.program;
if (!program.compilerOptions.noEmit) {
await validateDependencies(program, true);
}
if (!program.hasError()) {
const options = context.options;
if (!options["flavor"]) {
if (LibName === "@azure-tools/typespec-java") {
options["flavor"] = "azure";
}
}
let codeModel;
try {
const builder = new CodeModelBuilder(program, context);
codeModel = await builder.build();
}
catch (error) {
if (error instanceof DiagnosticError) {
// diagnostic thrown as error
program.reportDiagnostic(error.diagnostic);
}
else {
// unknown error
reportDiagnostic(program, {
code: "unknown-error",
format: {
errorMessage: `The emitter was unable to generate client code from this TypeSpec, please open an issue on https://github.com/microsoft/typespec, include TypeSpec source and all the diagnostic information in your submission.\nStack: error.stack`,
},
target: NoTarget,
});
trace(program, error.stack);
}
}
if (codeModel && !program.hasError() && !program.compilerOptions.noEmit) {
const __dirname = dirname(fileURLToPath(import.meta.url));
const moduleRoot = resolvePath(__dirname, "..", "..");
const outputPath = context.emitterOutputDir;
options["output-dir"] = getNormalizedAbsolutePath(outputPath, undefined);
options.arm = codeModel.arm;
if ((_c = (_b = (_a = codeModel.info) === null || _a === void 0 ? void 0 : _a.license) === null || _b === void 0 ? void 0 : _b.extensions) === null || _c === void 0 ? void 0 : _c.header) {
options["license-header"] = codeModel.info.license.extensions.header;
}
const codeModelFileName = resolvePath(outputPath, "./code-model.yaml");
await promises.mkdir(outputPath, { recursive: true }).catch((err) => {
if (err.code !== "EISDIR" && err.code !== "EEXIST") {
reportDiagnostic(program, {
code: "unknown-error",
format: { errorMessage: `Failed to create output directory: ${outputPath}.` },
target: NoTarget,
});
return;
}
});
await program.host.writeFile(codeModelFileName, dump(codeModel));
trace(program, `Code model file written to ${codeModelFileName}`);
const emitterOptions = JSON.stringify(options);
trace(program, `Emitter options ${emitterOptions}`);
const jarFileName = resolvePath(moduleRoot, "generator/http-client-generator/target", "emitter.jar");
trace(program, `Exec JAR ${jarFileName}`);
const javaArgs = [];
javaArgs.push(`-DemitterOptions=${emitterOptions}`);
if ((_d = options["dev-options"]) === null || _d === void 0 ? void 0 : _d.debug) {
javaArgs.push("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005");
}
if ((_e = options["dev-options"]) === null || _e === void 0 ? void 0 : _e.loglevel) {
javaArgs.push("-Dorg.slf4j.simpleLogger.defaultLogLevel=" + ((_f = options["dev-options"]) === null || _f === void 0 ? void 0 : _f.loglevel));
}
if ((_g = options["dev-options"]) === null || _g === void 0 ? void 0 : _g["java-temp-dir"]) {
javaArgs.push("-Dcodegen.java.temp.directory=" + ((_h = options["dev-options"]) === null || _h === void 0 ? void 0 : _h["java-temp-dir"]));
}
javaArgs.push("-jar");
javaArgs.push(jarFileName);
javaArgs.push(codeModelFileName);
try {
const result = await spawnAsync("java", javaArgs, { stdio: "pipe" });
reportJarOutput(program, result.stdout);
// trace(program, `Code generation log: ${result.stdout}`);
}
catch (error) {
if (error && "code" in error && error["code"] === "ENOENT") {
reportDiagnostic(program, {
code: "invalid-java-sdk-dependency",
target: NoTarget,
});
}
else {
if (error instanceof SpawnError) {
reportJarOutput(program, error.stdout);
// trace(program, `Code generation log: ${error.stdout}`);
}
// error in Java codegen, report as unknown error
reportDiagnostic(program, {
code: "unknown-error",
format: {
errorMessage: `The emitter was unable to generate client code from this TypeSpec, please open an issue on https://github.com/microsoft/typespec, include TypeSpec source and all the diagnostic information in your submission.`,
},
target: NoTarget,
});
}
}
if (!((_j = options["dev-options"]) === null || _j === void 0 ? void 0 : _j["generate-code-model"])) {
await program.host.rm(codeModelFileName);
}
}
}
}
function reportJarOutput(program, jarOutput) {
const lines = jarOutput.split("\n");
const logs = [];
// parse stdout to array of logs
let currentLog = undefined;
for (const line of lines) {
if (line.startsWith("TRACE ") ||
line.startsWith("DEBUG ") ||
line.startsWith("INFO ") ||
line.startsWith("WARN ") ||
line.startsWith("ERROR ")) {
if (currentLog) {
logs.push(currentLog);
}
currentLog = line;
}
else if (currentLog) {
currentLog = currentLog + "\n" + line;
}
}
if (currentLog) {
logs.push(currentLog);
}
// trace or report the logs, according to log level
for (const log of logs) {
if (log.startsWith("ERROR ")) {
reportDiagnostic(program, {
code: "generator-error",
format: {
errorMessage: log.substring(6),
},
target: NoTarget,
});
}
else if (log.startsWith("WARN ")) {
reportDiagnostic(program, {
code: "generator-warning",
format: {
warningMessage: log.substring(5),
},
target: NoTarget,
});
}
else {
const index = log.indexOf(" ");
trace(program, log.substring(index + 1));
}
}
}
//# sourceMappingURL=emitter.js.map