Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add severity levels to build errors #1285 #1544

Merged
merged 6 commits into from
May 21, 2024
Merged
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
1,058 changes: 563 additions & 495 deletions backend/protos/xyz/block/ftl/v1/schema/schema.pb.go

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions backend/protos/xyz/block/ftl/v1/schema/schema.proto
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,16 @@ message EnumVariant {
}

message Error {
enum ErrorLevel {
INFO = 0;
WARN = 1;
ERROR = 2;
}

string msg = 1;
Position pos = 2;
int64 endColumn = 3;
ErrorLevel level = 4;
}

message ErrorList {
Expand Down
31 changes: 26 additions & 5 deletions backend/schema/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,19 @@ import (
schemapb "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1/schema"
)

type ErrorLevel int

const (
INFO ErrorLevel = iota
WARN
ERROR
)

type Error struct {
Msg string `json:"msg" protobuf:"1"`
Pos Position `json:"pos" protobuf:"2"`
EndColumn int `json:"endCol" protobuf:"3"`
Msg string `json:"msg" protobuf:"1"`
Pos Position `json:"pos" protobuf:"2"`
EndColumn int `json:"endCol" protobuf:"3"`
Level ErrorLevel `json:"level" protobuf:"4"`
}

func (e Error) ToProto() *schemapb.Error {
Expand Down Expand Up @@ -67,11 +76,23 @@ func ErrorListFromProto(e *schemapb.ErrorList) *ErrorList {
}
}

func Errorf(pos Position, endColumn int, format string, args ...any) *Error {
err := Error{Msg: fmt.Sprintf(format, args...), Pos: pos, EndColumn: endColumn}
func makeError(level ErrorLevel, pos Position, endColumn int, format string, args ...any) *Error {
err := Error{Msg: fmt.Sprintf(format, args...), Pos: pos, EndColumn: endColumn, Level: level}
return &err
}

func Infof(pos Position, endColumn int, format string, args ...any) *Error {
return makeError(INFO, pos, endColumn, format, args...)
}

func Warnf(pos Position, endColumn int, format string, args ...any) *Error {
return makeError(WARN, pos, endColumn, format, args...)
}

func Errorf(pos Position, endColumn int, format string, args ...any) *Error {
return makeError(ERROR, pos, endColumn, format, args...)
}

func Wrapf(pos Position, endColumn int, err error, format string, args ...any) *Error {
if format == "" {
format = "%s"
Expand Down
17 changes: 17 additions & 0 deletions backend/schema/protobuf.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func generateStruct(t reflect.Type, messages map[string]string) {
if typesWithRuntime[t.Name()] {
fmt.Fprintf(w, "\n optional %sRuntime runtime = 31634;\n", name)
}
generateWellKnownNestedEnums(t, w)
fields := reflect.VisibleFields(t)
// Sort by protobuf tag
slices.SortFunc(fields, func(a, b reflect.StructField) int {
Expand Down Expand Up @@ -132,6 +133,18 @@ func generateStruct(t reflect.Type, messages map[string]string) {
messages[t.Name()] = w.String()
}

// generateWellKnownNestedEnums generates the well-known nested enums for a given reflect.Type.
// Reflection cannot discover type aliased enums, so they need to get generated manually.
func generateWellKnownNestedEnums(t reflect.Type, w *strings.Builder) {
Copy link
Collaborator

@alecthomas alecthomas May 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah awesome, I've been meaning to do something about enums for a while now.

This, and the "chicken and egg" problem of having the proto schema rely on the Go schema compiling and existing would be nice to solve in the general case. I think the permanent solution is to switch to static analysis. But this is great for now.

if (t == reflect.TypeOf(Error{})) {
fmt.Fprintf(w, " enum %s {\n", reflect.TypeOf(ErrorLevel(0)).Name())
fmt.Fprintf(w, " INFO = %d;\n", INFO)
fmt.Fprintf(w, " WARN = %d;\n", WARN)
fmt.Fprintf(w, " ERROR = %d;\n", ERROR)
fmt.Fprintf(w, " }\n")
}
}

func generateUnion(t reflect.Type, messages map[string]string) {
t = indirect(t)
if _, ok := messages[t.Name()]; ok {
Expand Down Expand Up @@ -166,6 +179,10 @@ func generateProtoType(t reflect.Type) string {
case reflect.String:
return "string"
case reflect.Int:
// determine if t is a well-known type aliased enum
if t == reflect.TypeOf(ErrorLevel(0)) {
return t.Name()
}
return "int64"
case reflect.Bool:
return "bool"
Expand Down
32 changes: 32 additions & 0 deletions frontend/src/protos/xyz/block/ftl/v1/schema/schema_pb.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion lsp/lsp.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,16 @@ func publishErrors(errByFilename map[string]errSet, s *Server) {
for _, e := range errs {
pp := e.Pos
sourceName := "ftl"
severity := protocol.DiagnosticSeverityError
var severity protocol.DiagnosticSeverity

switch e.Level {
case schema.ERROR:
severity = protocol.DiagnosticSeverityError
case schema.WARN:
severity = protocol.DiagnosticSeverityWarning
case schema.INFO:
severity = protocol.DiagnosticSeverityInformation
}

// If the end column is not set, set it to the length of the word.
if e.EndColumn <= pp.Column {
Expand Down
Loading