Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,13 @@ public static ArrayList<String> generateDescriptor(String command) throws CodeGe
" running the protoc executor. " + e.getMessage(), e);
}
if (process.exitValue() != 0) {
StringBuilder errMsg = new StringBuilder();
for (String line : output) {
errMsg.append(line).append(System.lineSeparator());
if (output.isEmpty()) {
throw new CodeGeneratorException("Proto compilation failed with exit code: " + process.exitValue());
} else {
String rawError = String.join(System.lineSeparator(), output);
String formattedError = formatProtoError(rawError);
throw new CodeGeneratorException(formattedError);
}
throw new CodeGeneratorException("Process exited with the following output: \n" + errMsg);
}
return output;
}
Expand All @@ -100,21 +102,53 @@ public static Process runProcess(String command) throws IOException {
}

public static void handleProcessExecutionErrors(Process process) throws CodeGeneratorException {
if (process.exitValue() != 0) {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream(),
StandardCharsets.UTF_8))) {
String err;
StringBuilder errMsg = new StringBuilder();
while ((err = bufferedReader.readLine()) != null) {
errMsg.append(System.lineSeparator()).append(err);
// Capture error stream before checking exit value to avoid "Stream closed" errors
StringBuilder errMsg = new StringBuilder();
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream(),
StandardCharsets.UTF_8))) {
String err;
while ((err = bufferedReader.readLine()) != null) {
if (!errMsg.isEmpty()) {
errMsg.append(System.lineSeparator());
}
throw new CodeGeneratorException(errMsg.toString());
} catch (IOException e) {
throw new CodeGeneratorException("Invalid command syntax. " + e.getMessage(), e);
errMsg.append(err);
}
} catch (IOException e) {
throw new CodeGeneratorException("Failed to read error output from protoc command. " + e.getMessage(), e);
}

// Now check exit value after reading error stream
if (process.exitValue() != 0) {
if (errMsg.isEmpty()) {
throw new CodeGeneratorException("Proto compilation failed with exit code: " + process.exitValue());
} else {
// Format error message to be more user-friendly
String formattedError = formatProtoError(errMsg.toString());
throw new CodeGeneratorException(formattedError);
}
}
}

/**
* Format protoc error messages to be more user-friendly.
*
* @param rawError The raw error output from protoc
* @return A formatted, user-friendly error message
*/
private static String formatProtoError(String rawError) {
StringBuilder formatted = new StringBuilder();
formatted.append("Error: Failed to generate Ballerina files from proto definition.")
.append(System.lineSeparator());
formatted.append(System.lineSeparator());
formatted.append("Proto compilation failed with the following error:")
.append(System.lineSeparator());
formatted.append(rawError);
formatted.append(System.lineSeparator());
formatted.append(System.lineSeparator());
formatted.append("Please check your .proto file for syntax errors and undefined types.");
return formatted.toString();
}

/**
* Resolve proto folder path from Proto file path.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@
import static io.ballerina.protoc.core.builder.balgen.BalGenConstants.PACKAGE_SEPARATOR;
import static io.ballerina.protoc.core.builder.syntaxtree.utils.ClientSampleSyntaxTreeUtils.generateSyntaxTreeForClientSample;
import static io.ballerina.protoc.core.builder.syntaxtree.utils.CommonUtils.removeStandardImports;
import static io.ballerina.protoc.core.utils.BalFileGenerationUtils.delete;
import static io.ballerina.protoc.core.utils.BalFileGenerationUtils.handleProcessExecutionErrors;
import static io.ballerina.protoc.core.utils.BalFileGenerationUtils.runProcess;
import static io.ballerina.protoc.core.BalFileGenerationUtils.delete;
import static io.ballerina.protoc.core.BalFileGenerationUtils.handleProcessExecutionErrors;
import static io.ballerina.protoc.core.BalFileGenerationUtils.runProcess;

/**
* Class is responsible of generating the ballerina stub which is mapping proto definition.
Expand Down

This file was deleted.