Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
39 changes: 39 additions & 0 deletions CMOD/ERROR_REPORTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# CMOD error reporting

CMOD writes diagnostics to standard error. LASSIE's Process Output window
already displays that stream and marks failed processes in red.

| Exit code | Meaning |
| --- | --- |
| 0 | The requested build completed. |
| 1 | A diagnosed project-input or output failure. |
| 2 | An unexpected C++ exception or a diagnosed internal error. |

For example, a missing configuration field produces:

```text
CMOD project error: A required project setting is missing.
Project: Example.dissco
Context: ProjectConfiguration.NumberOfChannels
Suggestion: Restore this setting in Project Properties, then save the project in LASSIE.
Build failed.
```

Project diagnostics cover unreadable or malformed project XML, missing or invalid
configuration, invalid numeric expressions and nested functions, missing object
references, invalid Select indices, functions used without an event context,
invalid child counts, and empty score staffs. Output diagnostics cover directory
creation, temporary library files, audio/score writes, and LilyPond failures.
Unexpected C++ exceptions ask the user to send developers the project, seed,
and diagnostic. Hard process faults and remaining legacy direct-exit paths
retain their existing handling; they are not made recoverable by these exceptions.

## Adding a diagnostic

Throw `CmodError` with a category, a specific reason, input context, and a
corrective action. Add outer context while rethrowing at a boundary that knows
the project field or expression. Do not discard an underlying parser's reason,
or classify an arbitrary `std::exception` as a user-input error.

`Main.cpp` reports the exception once and returns a nonzero exit code. A failed
run must not reach its `Build complete.` message.
404 changes: 274 additions & 130 deletions CMOD/src/Bottom.cpp

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions CMOD/src/CmodError.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef CMOD_ERROR_H
#define CMOD_ERROR_H

#include <ostream>
#include <stdexcept>
#include <string>

// Expected failures retain the input context and a useful next step while
// unwinding to the command-line boundary. Unexpected exceptions are internal.
class CmodError : public std::runtime_error {
public:
enum class Kind { Project, Output, Internal };

CmodError(Kind kind, const std::string& message,
const std::string& context, const std::string& suggestion)
: std::runtime_error(message), kind_(kind), context_(context),
suggestion_(suggestion) {}

void addContext(const std::string& context) {
context_ = context + (context_.empty() ? "" : " -> " + context_);
}

int exitCode() const { return kind_ == Kind::Internal ? 2 : 1; }

void report(std::ostream& output, const std::string& project) const {
const char* category = kind_ == Kind::Project ? "project"
: kind_ == Kind::Output ? "output" : "internal";
output << "CMOD " << category << " error: " << what() << '\n'
<< "Project: " << project << '\n';
if (!context_.empty())
output << "Context: " << context_ << '\n';
output << "Suggestion: " << suggestion_ << '\n'
<< "Build failed." << std::endl;
}

private:
Kind kind_;
std::string context_;
std::string suggestion_;
};

#endif
Loading
Loading