diff --git a/api/proto/sysml.pb.go b/api/proto/sysml.pb.go index abde04985..4ceaa67b8 100644 --- a/api/proto/sysml.pb.go +++ b/api/proto/sysml.pb.go @@ -4881,10 +4881,13 @@ func (x *UnitFactor) GetExponent() float64 { // Diagnostic represents a parse/semantic error or warning type Diagnostic struct { - state protoimpl.MessageState `protogen:"open.v1"` - Severity string `protobuf:"bytes,1,opt,name=severity,proto3" json:"severity,omitempty"` // "error", "warning", "info" - Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` - Span *Span `protobuf:"bytes,3,opt,name=span,proto3" json:"span,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Severity string `protobuf:"bytes,1,opt,name=severity,proto3" json:"severity,omitempty"` // "error", "warning", "info" + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + Span *Span `protobuf:"bytes,3,opt,name=span,proto3" json:"span,omitempty"` + // Stable identifier to branch on instead of the message: a pass or rule code, + // "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned. + Code string `protobuf:"bytes,4,opt,name=code,proto3" json:"code,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -4940,6 +4943,13 @@ func (x *Diagnostic) GetSpan() *Span { return nil } +func (x *Diagnostic) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + // Span represents a source location type Span struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -5117,6 +5127,8 @@ type ServerInfoResponse struct { // and answers with typed rows. // "render_document" - the RenderDocument RPC renders a named document to // Markdown. + // "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + // finding none was assigned; without it every code is empty. Capabilities []string `protobuf:"bytes,2,rep,name=capabilities,proto3" json:"capabilities,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -6984,12 +6996,13 @@ const file_sysml_proto_rawDesc = "" + "\n" + "UnitFactor\x12\x17\n" + "\aunit_id\x18\x01 \x01(\tR\x06unitId\x12\x1a\n" + - "\bexponent\x18\x02 \x01(\x01R\bexponent\"c\n" + + "\bexponent\x18\x02 \x01(\x01R\bexponent\"w\n" + "\n" + "Diagnostic\x12\x1a\n" + "\bseverity\x18\x01 \x01(\tR\bseverity\x12\x18\n" + "\amessage\x18\x02 \x01(\tR\amessage\x12\x1f\n" + - "\x04span\x18\x03 \x01(\v2\v.sysml.SpanR\x04span\"\x8a\x01\n" + + "\x04span\x18\x03 \x01(\v2\v.sysml.SpanR\x04span\x12\x12\n" + + "\x04code\x18\x04 \x01(\tR\x04code\"\x8a\x01\n" + "\x04Span\x12\x12\n" + "\x04file\x18\x01 \x01(\tR\x04file\x12\x1d\n" + "\n" + diff --git a/api/proto/sysml.proto b/api/proto/sysml.proto index ecd20bd8a..8650b4ca3 100644 --- a/api/proto/sysml.proto +++ b/api/proto/sysml.proto @@ -836,6 +836,9 @@ message Diagnostic { string severity = 1; // "error", "warning", "info" string message = 2; Span span = 3; + // Stable identifier to branch on instead of the message: a pass or rule code, + // "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned. + string code = 4; } // Span represents a source location @@ -911,6 +914,8 @@ message ServerInfoResponse { // and answers with typed rows. // "render_document" - the RenderDocument RPC renders a named document to // Markdown. + // "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + // finding none was assigned; without it every code is empty. repeated string capabilities = 2; } diff --git a/changes/unreleased/diagnostic-wire-code.added.md b/changes/unreleased/diagnostic-wire-code.added.md new file mode 100644 index 000000000..276dbe2df --- /dev/null +++ b/changes/unreleased/diagnostic-wire-code.added.md @@ -0,0 +1,7 @@ +- **A wire `Diagnostic` carries its `code`.** The gRPC/Connect `Diagnostic` message gains + `string code = 4`, the stable identifier the runtime already assigns: `syntax` for a parse + error, the pass or rule code for a validation finding, `choice-point` and `guard-unevaluable` + for a run's notes. Every response that carries diagnostics carries it, so a client branches on + `code` instead of a message prefix; a diagnostic whose producer assigned no code sends it empty. + A service that populates it advertises the `diagnostic_codes` capability. The Go, Python, + Node, Rust and Java clients expose it as `Diagnostic.code` and name the capability. diff --git a/client/opensysml/client_test.go b/client/opensysml/client_test.go index e5ce87873..a73845ac9 100644 --- a/client/opensysml/client_test.go +++ b/client/opensysml/client_test.go @@ -73,6 +73,36 @@ func TestASyntaxErrorIsADiagnosticNotAnError(t *testing.T) { if len(model.Diagnostics) == 0 { t.Error("broken source parsed without diagnostics") } + for _, diag := range model.Diagnostics { + if diag.Code != "syntax" { + t.Errorf("syntax error coded %q, want syntax: %s", diag.Code, diag.Message) + } + } +} + +func TestADiagnosticCarriesItsCode(t *testing.T) { + client := newClient(t) + info, err := client.ServerInfo(context.Background()) + if err != nil { + t.Fatalf("ServerInfo: %v", err) + } + if !info.Has(opensysml.CapabilityDiagnosticCodes) { + t.Errorf("capabilities %v do not include %s", info.Capabilities, opensysml.CapabilityDiagnosticCodes) + } + model, err := client.ParseSource(context.Background(), "package P { part def W { part hub : Missing; } }") + if err != nil { + t.Fatalf("ParseSource: %v", err) + } + found := false + for _, diag := range model.Diagnostics { + if diag.Code == "" { + t.Errorf("diagnostic without a code: %s", diag.Message) + } + found = found || diag.Code == "unresolved" + } + if !found { + t.Errorf("no unresolved diagnostic among %v", model.Diagnostics) + } } func TestAMissingFileIsNotFound(t *testing.T) { diff --git a/client/opensysml/convert.go b/client/opensysml/convert.go index eee63be49..6c6d939d7 100644 --- a/client/opensysml/convert.go +++ b/client/opensysml/convert.go @@ -67,7 +67,7 @@ func diagnosticsFromProto(diags []*pb.Diagnostic) []Diagnostic { } out := make([]Diagnostic, 0, len(diags)) for _, diag := range diags { - converted := Diagnostic{Severity: diag.Severity, Message: diag.Message} + converted := Diagnostic{Severity: diag.Severity, Message: diag.Message, Code: diag.Code} if diag.Span != nil { converted.Span = &Span{ File: diag.Span.File, diff --git a/client/opensysml/types.go b/client/opensysml/types.go index 4a039c438..9936db8f1 100644 --- a/client/opensysml/types.go +++ b/client/opensysml/types.go @@ -32,6 +32,7 @@ const ( CapabilityStructuredValues = sysmlgrpc.CapabilityStructuredValues CapabilityMeasurementRefs = sysmlgrpc.CapabilityMeasurementRefs CapabilityFunctionValues = sysmlgrpc.CapabilityFunctionValues + CapabilityDiagnosticCodes = sysmlgrpc.CapabilityDiagnosticCodes CapabilityVerificationVerdicts = sysmlgrpc.CapabilityVerificationVerdicts ) @@ -175,6 +176,9 @@ type Diagnostic struct { // Severity is SeverityError, SeverityWarning or SeverityInfo. Severity string Message string + // Code identifies what was found, stable across message wording ("syntax", a + // validation code, "choice-point", "guard-unevaluable"); empty when none was assigned. + Code string // Span locates the finding in its source, nil when it has no location. Span *Span } diff --git a/clients/java/README.md b/clients/java/README.md index cf3e63bf4..b2a9ba122 100644 --- a/clients/java/README.md +++ b/clients/java/README.md @@ -39,7 +39,12 @@ records (`IntegerValue`, `RealValue`, `ComplexValue`, `QuantityValue`, `ArrayVal `VectorValue`, `VectorQuantityValue`, `MeasurementRefValue`, `FunctionValue`, `EnumerationValue`, `InstanceReference`, `Sequence`, `NullValue`, `UnsetValue`, …), and `Symbol`, `Diagnostic`, `Instance` and `Instantiation` are records with copied collections. -No generated protobuf message or builder appears in the public API. +No generated protobuf message or builder appears in the public API. A `Diagnostic` +is `(severity, message, code, span)`; `code()` is the identifier to branch on +(`"syntax"`, a validation code such as `"unresolved"`, `"choice-point"`, +`"guard-unevaluable"`; `""` when the service assigned none), `message()` is for reading. A +service that populates `code` advertises `Capabilities.DIAGNOSTIC_CODES`; without it every +code is `""`. ## Exceptions: unchecked, and the distinction that matters diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Capabilities.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Capabilities.java index 13debef96..b25777bee 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Capabilities.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Capabilities.java @@ -53,6 +53,9 @@ public final class Capabilities { /** The unbounded value {@code *} travels as itself rather than as an unsupported null. */ public static final String INFINITY_VALUE = "infinity_value"; + /** {@code Diagnostic.code} is populated, so an empty code is a finding none was assigned. */ + public static final String DIAGNOSTIC_CODES = "diagnostic_codes"; + /** The {@code ApplyEdits} RPC edits a parsed model's own source. */ public static final String APPLY_EDITS = "apply_edits"; diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Diagnostic.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Diagnostic.java index 66fd4a117..1a318e640 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Diagnostic.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/Diagnostic.java @@ -9,20 +9,25 @@ * * @param severity how serious the finding is * @param message the finding, as the service words it + * @param code stable identifier of what was found, independent of the message wording: a + * validation code, {@code "syntax"}, or {@code "choice-point"} / {@code "guard-unevaluable"} + * on a run; empty when the service assigned none * @param span where in the source it is, absent when the service located none */ -public record Diagnostic(Severity severity, String message, Optional span) { +public record Diagnostic(Severity severity, String message, String code, Optional span) { /** * Creates a diagnostic. * * @param severity the severity, never {@code null} * @param message the message, never {@code null} + * @param code the code, empty rather than {@code null} when there is none * @param span the source location, absent when unlocated */ public Diagnostic { Objects.requireNonNull(severity, "severity"); Objects.requireNonNull(message, "message"); + Objects.requireNonNull(code, "code"); Objects.requireNonNull(span, "span"); } diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/ModelException.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/ModelException.java index add21cb7f..77f714038 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/ModelException.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/ModelException.java @@ -20,7 +20,7 @@ */ public class ModelException extends OpenSysMLException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 2L; private static final int MAX_SERIALIZED_DIAGNOSTICS = 100_000; private transient List diagnostics; @@ -55,6 +55,7 @@ private void writeObject(ObjectOutputStream stream) throws IOException { for (Diagnostic diagnostic : diagnostics) { stream.writeObject(diagnostic.severity()); stream.writeObject(diagnostic.message()); + stream.writeObject(diagnostic.code()); stream.writeBoolean(diagnostic.span().isPresent()); if (diagnostic.span().isPresent()) { Diagnostic.Span span = diagnostic.span().orElseThrow(); @@ -81,8 +82,10 @@ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFo for (int index = 0; index < count; index++) { Object severity = stream.readObject(); Object message = stream.readObject(); + Object code = stream.readObject(); if (!(severity instanceof Diagnostic.Severity diagnosticSeverity) - || !(message instanceof String diagnosticMessage)) { + || !(message instanceof String diagnosticMessage) + || !(code instanceof String diagnosticCode)) { throw new InvalidObjectException("invalid diagnostic"); } Optional span = Optional.empty(); @@ -100,7 +103,7 @@ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFo stream.readInt(), stream.readInt())); } - restored.add(new Diagnostic(diagnosticSeverity, diagnosticMessage, span)); + restored.add(new Diagnostic(diagnosticSeverity, diagnosticMessage, diagnosticCode, span)); } diagnostics = List.copyOf(restored); } diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/internal/Protos.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/internal/Protos.java index 6dfb81c77..9f742ff88 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/internal/Protos.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/internal/Protos.java @@ -221,6 +221,7 @@ public static List diagnostics( new Diagnostic( Diagnostic.Severity.fromWireName(diagnostic.getSeverity()), diagnostic.getMessage(), + diagnostic.getCode(), diagnostic.hasSpan() ? Optional.of(span(diagnostic.getSpan())) : Optional.empty())); } return List.copyOf(read); diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Diagnostic.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Diagnostic.java index 6dfa36f2f..5f928768c 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Diagnostic.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Diagnostic.java @@ -34,6 +34,7 @@ private Diagnostic(com.google.protobuf.GeneratedMessage.Builder builder) { private Diagnostic() { severity_ = ""; message_ = ""; + code_ = ""; } public static final com.google.protobuf.Descriptors.Descriptor @@ -162,6 +163,55 @@ public org.openmbee.opensysml.proto.SpanOrBuilder getSpanOrBuilder() { return span_ == null ? org.openmbee.opensysml.proto.Span.getDefaultInstance() : span_; } + public static final int CODE_FIELD_NUMBER = 4; + @SuppressWarnings("serial") + private volatile java.lang.Object code_ = ""; + /** + *
+   * Stable identifier to branch on instead of the message: a pass or rule code,
+   * "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned.
+   * 
+ * + * string code = 4 [json_name = "code"]; + * @return The code. + */ + @java.lang.Override + public java.lang.String getCode() { + java.lang.Object ref = code_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + code_ = s; + return s; + } + } + /** + *
+   * Stable identifier to branch on instead of the message: a pass or rule code,
+   * "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned.
+   * 
+ * + * string code = 4 [json_name = "code"]; + * @return The bytes for code. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getCodeBytes() { + java.lang.Object ref = code_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + code_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + private byte memoizedIsInitialized = -1; @java.lang.Override public final boolean isInitialized() { @@ -185,6 +235,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (((bitField0_ & 0x00000001) != 0)) { output.writeMessage(3, getSpan()); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(code_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 4, code_); + } getUnknownFields().writeTo(output); } @@ -204,6 +257,9 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeMessageSize(3, getSpan()); } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(code_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(4, code_); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -228,6 +284,8 @@ public boolean equals(final java.lang.Object obj) { if (!getSpan() .equals(other.getSpan())) return false; } + if (!getCode() + .equals(other.getCode())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; } @@ -247,6 +305,8 @@ public int hashCode() { hash = (37 * hash) + SPAN_FIELD_NUMBER; hash = (53 * hash) + getSpan().hashCode(); } + hash = (37 * hash) + CODE_FIELD_NUMBER; + hash = (53 * hash) + getCode().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -395,6 +455,7 @@ public Builder clear() { spanBuilder_.dispose(); spanBuilder_ = null; } + code_ = ""; return this; } @@ -441,6 +502,9 @@ private void buildPartial0(org.openmbee.opensysml.proto.Diagnostic result) { : spanBuilder_.build(); to_bitField0_ |= 0x00000001; } + if (((from_bitField0_ & 0x00000008) != 0)) { + result.code_ = code_; + } result.bitField0_ |= to_bitField0_; } @@ -469,6 +533,11 @@ public Builder mergeFrom(org.openmbee.opensysml.proto.Diagnostic other) { if (other.hasSpan()) { mergeSpan(other.getSpan()); } + if (!other.getCode().isEmpty()) { + code_ = other.code_; + bitField0_ |= 0x00000008; + onChanged(); + } this.mergeUnknownFields(other.getUnknownFields()); onChanged(); return this; @@ -512,6 +581,11 @@ public Builder mergeFrom( bitField0_ |= 0x00000004; break; } // case 26 + case 34: { + code_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000008; + break; + } // case 34 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { done = true; // was an endgroup tag @@ -814,6 +888,103 @@ public org.openmbee.opensysml.proto.SpanOrBuilder getSpanOrBuilder() { return spanBuilder_; } + private java.lang.Object code_ = ""; + /** + *
+     * Stable identifier to branch on instead of the message: a pass or rule code,
+     * "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned.
+     * 
+ * + * string code = 4 [json_name = "code"]; + * @return The code. + */ + public java.lang.String getCode() { + java.lang.Object ref = code_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + code_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
+     * Stable identifier to branch on instead of the message: a pass or rule code,
+     * "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned.
+     * 
+ * + * string code = 4 [json_name = "code"]; + * @return The bytes for code. + */ + public com.google.protobuf.ByteString + getCodeBytes() { + java.lang.Object ref = code_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + code_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
+     * Stable identifier to branch on instead of the message: a pass or rule code,
+     * "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned.
+     * 
+ * + * string code = 4 [json_name = "code"]; + * @param value The code to set. + * @return This builder for chaining. + */ + public Builder setCode( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + code_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + /** + *
+     * Stable identifier to branch on instead of the message: a pass or rule code,
+     * "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned.
+     * 
+ * + * string code = 4 [json_name = "code"]; + * @return This builder for chaining. + */ + public Builder clearCode() { + code_ = getDefaultInstance().getCode(); + bitField0_ = (bitField0_ & ~0x00000008); + onChanged(); + return this; + } + /** + *
+     * Stable identifier to branch on instead of the message: a pass or rule code,
+     * "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned.
+     * 
+ * + * string code = 4 [json_name = "code"]; + * @param value The bytes for code to set. + * @return This builder for chaining. + */ + public Builder setCodeBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + code_ = value; + bitField0_ |= 0x00000008; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:sysml.Diagnostic) } diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/DiagnosticOrBuilder.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/DiagnosticOrBuilder.java index 8a8c4abdb..a4eff47d9 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/DiagnosticOrBuilder.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/DiagnosticOrBuilder.java @@ -56,4 +56,26 @@ public interface DiagnosticOrBuilder extends * .sysml.Span span = 3 [json_name = "span"]; */ org.openmbee.opensysml.proto.SpanOrBuilder getSpanOrBuilder(); + + /** + *
+   * Stable identifier to branch on instead of the message: a pass or rule code,
+   * "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned.
+   * 
+ * + * string code = 4 [json_name = "code"]; + * @return The code. + */ + java.lang.String getCode(); + /** + *
+   * Stable identifier to branch on instead of the message: a pass or rule code,
+   * "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned.
+   * 
+ * + * string code = 4 [json_name = "code"]; + * @return The bytes for code. + */ + com.google.protobuf.ByteString + getCodeBytes(); } diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ServerInfoResponse.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ServerInfoResponse.java index c4311fadf..c0f626e26 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ServerInfoResponse.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ServerInfoResponse.java @@ -161,6 +161,8 @@ public java.lang.String getVersion() { * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -226,6 +228,8 @@ public java.lang.String getVersion() { * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -290,6 +294,8 @@ public int getCapabilitiesCount() { * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -355,6 +361,8 @@ public java.lang.String getCapabilities(int index) { * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -869,6 +877,8 @@ private void ensureCapabilitiesIsMutable() { * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -935,6 +945,8 @@ private void ensureCapabilitiesIsMutable() { * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -999,6 +1011,8 @@ public int getCapabilitiesCount() { * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -1064,6 +1078,8 @@ public java.lang.String getCapabilities(int index) { * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -1130,6 +1146,8 @@ public java.lang.String getCapabilities(int index) { * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -1202,6 +1220,8 @@ public Builder setCapabilities( * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -1273,6 +1293,8 @@ public Builder addCapabilities( * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -1344,6 +1366,8 @@ public Builder addAllCapabilities( * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -1412,6 +1436,8 @@ public Builder clearCapabilities() { * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ServerInfoResponseOrBuilder.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ServerInfoResponseOrBuilder.java index d38de77f3..15c8bf03c 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ServerInfoResponseOrBuilder.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/ServerInfoResponseOrBuilder.java @@ -90,6 +90,8 @@ public interface ServerInfoResponseOrBuilder extends * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -153,6 +155,8 @@ public interface ServerInfoResponseOrBuilder extends * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -215,6 +219,8 @@ public interface ServerInfoResponseOrBuilder extends * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; @@ -278,6 +284,8 @@ public interface ServerInfoResponseOrBuilder extends * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * * repeated string capabilities = 2 [json_name = "capabilities"]; diff --git a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Sysml.java b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Sysml.java index 37099f9c3..ab9308b4e 100644 --- a/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Sysml.java +++ b/clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Sysml.java @@ -746,156 +746,156 @@ public static void registerAllExtensions( "eNum\022\033\n\tscale_den\030\002 \001(\001R\010scaleDen\022+\n\007fac" + "tors\030\003 \003(\0132\021.sysml.UnitFactorR\007factors\"A" + "\n\nUnitFactor\022\027\n\007unit_id\030\001 \001(\tR\006unitId\022\032\n" + - "\010exponent\030\002 \001(\001R\010exponent\"c\n\nDiagnostic\022" + + "\010exponent\030\002 \001(\001R\010exponent\"w\n\nDiagnostic\022" + "\032\n\010severity\030\001 \001(\tR\010severity\022\030\n\007message\030\002" + " \001(\tR\007message\022\037\n\004span\030\003 \001(\0132\013.sysml.Span" + - "R\004span\"\212\001\n\004Span\022\022\n\004file\030\001 \001(\tR\004file\022\035\n\ns" + - "tart_line\030\002 \001(\005R\tstartLine\022\033\n\tstart_col\030" + - "\003 \001(\005R\010startCol\022\031\n\010end_line\030\004 \001(\005R\007endLi" + - "ne\022\027\n\007end_col\030\005 \001(\005R\006endCol\"\023\n\021ServerInf" + - "oRequest\"R\n\022ServerInfoResponse\022\030\n\007versio" + - "n\030\001 \001(\tR\007version\022\"\n\014capabilities\030\002 \003(\tR\014" + - "capabilities\"p\n\014QueryRequest\022\035\n\nmodel_ha" + - "sh\030\001 \001(\tR\tmodelHash\022\"\n\005query\030\002 \001(\0132\014.sys" + - "ml.QueryR\005query\022\035\n\noslc_query\030\003 \001(\tR\tosl" + - "cQuery\"F\n\rQueryResponse\0225\n\010elements\030\001 \003(" + - "\0132\031.sysml.QueryResultElementR\010elements\"^" + - "\n\005Query\022\024\n\005scope\030\001 \003(\tR\005scope\022\026\n\006select\030" + - "\002 \003(\tR\006select\022\'\n\005where\030\003 \001(\0132\021.sysml.Con" + - "straintR\005where\"\222\001\n\nConstraint\022:\n\tprimiti" + - "ve\030\001 \001(\0132\032.sysml.PrimitiveConstraintH\000R\t" + - "primitive\022:\n\tcomposite\030\002 \001(\0132\032.sysml.Com" + - "positeConstraintH\000R\tcompositeB\014\n\nconstra" + - "int\"\227\001\n\023PrimitiveConstraint\022\030\n\007inverse\030\001" + - " \001(\010R\007inverse\022\032\n\010property\030\002 \001(\tR\010propert" + - "y\0224\n\010operator\030\003 \001(\0162\030.sysml.PrimitiveOpe" + - "ratorR\010operator\022\024\n\005value\030\004 \003(\tR\005value\"~\n" + - "\023CompositeConstraint\0224\n\010operator\030\001 \001(\0162\030" + - ".sysml.CompositeOperatorR\010operator\0221\n\nco" + - "nstraint\030\002 \003(\0132\021.sysml.ConstraintR\nconst" + - "raint\"\302\001\n\022QueryResultElement\022\016\n\002id\030\001 \001(\t" + - "R\002id\022\022\n\004type\030\002 \001(\tR\004type\022I\n\nproperties\030\003" + - " \003(\0132).sysml.QueryResultElement.Properti" + - "esEntryR\nproperties\032=\n\017PropertiesEntry\022\020" + - "\n\003key\030\001 \001(\tR\003key\022\024\n\005value\030\002 \001(\tR\005value:\002" + - "8\001\"\220\001\n\nSweepRange\022\034\n\tparameter\030\001 \001(\tR\tpa" + - "rameter\022\"\n\005start\030\002 \001(\0132\014.sysml.ValueR\005st" + - "art\022\036\n\003end\030\003 \001(\0132\014.sysml.ValueR\003end\022 \n\004s" + - "tep\030\004 \001(\0132\014.sysml.ValueR\004step\"\244\003\n\017RunSwe" + - "epRequest\022\035\n\nmodel_hash\030\001 \001(\tR\tmodelHash" + - "\022\033\n\tsymbol_id\030\002 \001(\tR\010symbolId\022*\n\021subject" + - "_symbol_id\030\003 \001(\tR\017subjectSymbolId\022*\n\targ" + - "uments\030\004 \003(\0132\014.sysml.ValueR\targuments\022S\n" + - "\017named_arguments\030\005 \003(\0132*.sysml.RunSweepR" + - "equest.NamedArgumentsEntryR\016namedArgumen" + - "ts\022)\n\006ranges\030\006 \003(\0132\021.sysml.SweepRangeR\006r" + - "anges\022\030\n\007samples\030\007 \001(\003R\007samples\022\022\n\004seed\030" + - "\010 \001(\004R\004seed\032O\n\023NamedArgumentsEntry\022\020\n\003ke" + - "y\030\001 \001(\tR\003key\022\"\n\005value\030\002 \001(\0132\014.sysml.Valu" + - "eR\005value:\0028\001\"\210\002\n\010SweepRow\022)\n\006inputs\030\001 \003(" + - "\0132\021.sysml.CalcOutputR\006inputs\022+\n\007outputs\030" + - "\002 \003(\0132\021.sysml.CalcOutputR\007outputs\022*\n\010ver" + - "dicts\030\003 \003(\0132\016.sysml.VerdictR\010verdicts\022%\n" + - "\016elapsed_micros\030\004 \001(\003R\relapsedMicros\022\024\n\005" + - "error\030\005 \001(\tR\005error\022;\n\016failure_reason\030\006 \001" + - "(\0162\024.sysml.FailureReasonR\rfailureReason\"" + - "\274\002\n\020RunSweepResponse\022#\n\004rows\030\001 \003(\0132\017.sys" + - "ml.SweepRowR\004rows\022\036\n\nparameters\030\002 \003(\tR\np" + - "arameters\022\030\n\007sampled\030\003 \001(\010R\007sampled\022\022\n\004s" + - "eed\030\004 \001(\004R\004seed\022\024\n\005error\030\005 \001(\tR\005error\0223\n" + - "\013diagnostics\030\006 \003(\0132\021.sysml.DiagnosticR\013d" + - "iagnostics\022;\n\016failure_reason\030\007 \001(\0162\024.sys" + - "ml.FailureReasonR\rfailureReason\022-\n\tinsta" + - "nces\030\010 \003(\0132\017.sysml.InstanceR\tinstances\"\214" + - "\001\n\027RunDocumentQueryRequest\022\035\n\nmodel_hash" + - "\030\001 \001(\tR\tmodelHash\022\031\n\010query_id\030\002 \001(\tR\007que" + - "ryId\0227\n\010bindings\030\003 \003(\0132\033.sysml.DocumentQ" + - "ueryBindingR\010bindings\"b\n\024DocumentQueryBi" + - "nding\022\034\n\tparameter\030\001 \001(\tR\tparameter\022,\n\006v" + - "alues\030\002 \003(\0132\024.sysml.DocumentValueR\006value" + - "s\"\256\002\n\rDocumentValue\022\037\n\nelement_id\030\001 \001(\tH" + - "\000R\telementId\022#\n\014string_value\030\002 \001(\tH\000R\013st" + - "ringValue\022\035\n\tint_value\030\003 \001(\003H\000R\010intValue" + - "\022\037\n\nreal_value\030\004 \001(\001H\000R\trealValue\022\037\n\nboo" + - "l_value\030\005 \001(\010H\000R\tboolValue\022\034\n\010infinity\030\006" + - " \001(\010H\000R\010infinity\022-\n\010quantity\030\010 \001(\0132\017.sys" + - "ml.QuantityH\000R\010quantity\022!\n\014element_type\030" + - "\007 \001(\tR\013elementTypeB\006\n\004kind\")\n\023DocumentQu" + - "eryColumn\022\022\n\004name\030\001 \001(\tR\004name\"A\n\021Documen" + - "tQueryCell\022,\n\006values\030\001 \003(\0132\024.sysml.Docum" + - "entValueR\006values\"r\n\020DocumentQueryRow\022.\n\007" + - "element\030\001 \001(\0132\024.sysml.DocumentValueR\007ele" + - "ment\022.\n\005cells\030\002 \003(\0132\030.sysml.DocumentQuer" + - "yCellR\005cells\"}\n\030RunDocumentQueryResponse" + - "\0224\n\007columns\030\001 \003(\0132\032.sysml.DocumentQueryC" + - "olumnR\007columns\022+\n\004rows\030\002 \003(\0132\027.sysml.Doc" + - "umentQueryRowR\004rows\"W\n\025RenderDocumentReq" + - "uest\022\035\n\nmodel_hash\030\001 \001(\tR\tmodelHash\022\037\n\013d" + - "ocument_id\030\002 \001(\tR\ndocumentId\"4\n\026RenderDo" + - "cumentResponse\022\032\n\010markdown\030\001 \001(\tR\010markdo" + - "wn*\223\001\n\rFailureReason\022\036\n\032FAILURE_REASON_U" + - "NSPECIFIED\020\000\022\035\n\031FAILURE_REASON_EVALUATIO" + - "N\020\001\022\035\n\031FAILURE_REASON_WRONG_KIND\020\002\022$\n FA" + - "ILURE_REASON_AMBIGUOUS_SUBJECT\020\003*\235\004\n\013Edi" + - "tFailure\022\034\n\030EDIT_FAILURE_UNSPECIFIED\020\000\022\036" + - "\n\032EDIT_FAILURE_NO_OPERATIONS\020\001\022\037\n\033EDIT_F" + - "AILURE_UNKNOWN_TARGET\020\002\022!\n\035EDIT_FAILURE_" + - "AMBIGUOUS_TARGET\020\003\022\033\n\027EDIT_FAILURE_NOT_V" + - "ALUED\020\004\022\036\n\032EDIT_FAILURE_INVALID_VALUE\020\005\022" + - "\035\n\031EDIT_FAILURE_INVALID_NAME\020\006\022\032\n\026EDIT_F" + - "AILURE_NOT_NAMED\020\007\022\"\n\036EDIT_FAILURE_RENAM" + - "E_REFERENCED\020\010\022\"\n\036EDIT_FAILURE_OVERLAPPI" + - "NG_EDITS\020\t\022\037\n\033EDIT_FAILURE_RESULT_INVALI" + - "D\020\n\022\036\n\032EDIT_FAILURE_OWNER_UNKNOWN\020\013\022$\n E" + - "DIT_FAILURE_OWNER_NOT_NAMESPACE\020\014\022\035\n\031EDI" + - "T_FAILURE_ILLEGAL_KIND\020\r\022\"\n\036EDIT_FAILURE" + - "_MEMBER_NAME_TAKEN\020\016\022\"\n\036EDIT_FAILURE_DEL" + - "ETE_REFERENCED\020\017*\222\001\n\021PrimitiveOperator\022\"" + - "\n\036PRIMITIVE_OPERATOR_UNSPECIFIED\020\000\022\034\n\030PR" + - "IMITIVE_OPERATOR_EQUAL\020\001\022\036\n\032PRIMITIVE_OP" + - "ERATOR_GREATER\020\002\022\033\n\027PRIMITIVE_OPERATOR_L" + - "ESS\020\003*n\n\021CompositeOperator\022\"\n\036COMPOSITE_" + - "OPERATOR_UNSPECIFIED\020\000\022\032\n\026COMPOSITE_OPER" + - "ATOR_AND\020\001\022\031\n\025COMPOSITE_OPERATOR_OR\020\0022\244\013" + - "\n\014SysMLService\022D\n\rGetServerInfo\022\030.sysml." + - "ServerInfoRequest\032\031.sysml.ServerInfoResp" + - "onse\022>\n\tParseFile\022\027.sysml.ParseFileReque" + - "st\032\030.sysml.ParseFileResponse\022G\n\014ParseSou" + - "rces\022\032.sysml.ParseSourcesRequest\032\033.sysml" + - ".ParseSourcesResponse\022;\n\tGetSymbol\022\027.sys" + - "ml.GetSymbolRequest\032\025.sysml.SymbolRespon" + - "se\022G\n\016GetDiagnostics\022\031.sysml.Diagnostics" + - "Request\032\032.sysml.DiagnosticsResponse\022;\n\010E" + - "valuate\022\026.sysml.EvaluateRequest\032\027.sysml." + - "EvaluateResponse\022D\n\013Instantiate\022\031.sysml." + - "InstantiateRequest\032\032.sysml.InstantiateRe" + - "sponse\022J\n\rExecuteAction\022\033.sysml.ExecuteA" + - "ctionRequest\032\034.sysml.ExecuteActionRespon" + - "se\022G\n\014ExecuteState\022\032.sysml.ExecuteStateR" + - "equest\032\033.sysml.ExecuteStateResponse\0228\n\007C" + - "onvert\022\025.sysml.ConvertRequest\032\026.sysml.Co" + - "nvertResponse\022A\n\nApplyEdits\022\030.sysml.Appl" + - "yEditsRequest\032\031.sysml.ApplyEditsResponse" + - "\022S\n\020VerifyConstraint\022\036.sysml.VerifyConst" + - "raintRequest\032\037.sysml.VerifyConstraintRes" + - "ponse\022V\n\021VerifyRequirement\022\037.sysml.Verif" + - "yRequirementRequest\032 .sysml.VerifyRequir" + - "ementResponse\022Y\n\022VerifySatisfaction\022 .sy" + - "sml.VerifySatisfactionRequest\032!.sysml.Ve" + - "rifySatisfactionResponse\022G\n\014EvaluateCalc" + - "\022\032.sysml.EvaluateCalcRequest\032\033.sysml.Eva" + - "luateCalcResponse\022D\n\013RunAnalysis\022\031.sysml" + - ".RunAnalysisRequest\032\032.sysml.RunAnalysisR" + - "esponse\022;\n\010RunSweep\022\026.sysml.RunSweepRequ" + - "est\032\027.sysml.RunSweepResponse\0222\n\005Query\022\023." + - "sysml.QueryRequest\032\024.sysml.QueryResponse" + - "\022S\n\020RunDocumentQuery\022\036.sysml.RunDocument", - "QueryRequest\032\037.sysml.RunDocumentQueryRes" + - "ponse\022M\n\016RenderDocument\022\034.sysml.RenderDo" + - "cumentRequest\032\035.sysml.RenderDocumentResp" + - "onseBJ\n\034org.openmbee.opensysml.protoP\001Z(" + - "github.com/Open-MBEE/OpenSysML/api/proto" + - "b\006proto3" + "R\004span\022\022\n\004code\030\004 \001(\tR\004code\"\212\001\n\004Span\022\022\n\004f" + + "ile\030\001 \001(\tR\004file\022\035\n\nstart_line\030\002 \001(\005R\tsta" + + "rtLine\022\033\n\tstart_col\030\003 \001(\005R\010startCol\022\031\n\010e" + + "nd_line\030\004 \001(\005R\007endLine\022\027\n\007end_col\030\005 \001(\005R" + + "\006endCol\"\023\n\021ServerInfoRequest\"R\n\022ServerIn" + + "foResponse\022\030\n\007version\030\001 \001(\tR\007version\022\"\n\014" + + "capabilities\030\002 \003(\tR\014capabilities\"p\n\014Quer" + + "yRequest\022\035\n\nmodel_hash\030\001 \001(\tR\tmodelHash\022" + + "\"\n\005query\030\002 \001(\0132\014.sysml.QueryR\005query\022\035\n\no" + + "slc_query\030\003 \001(\tR\toslcQuery\"F\n\rQueryRespo" + + "nse\0225\n\010elements\030\001 \003(\0132\031.sysml.QueryResul" + + "tElementR\010elements\"^\n\005Query\022\024\n\005scope\030\001 \003" + + "(\tR\005scope\022\026\n\006select\030\002 \003(\tR\006select\022\'\n\005whe" + + "re\030\003 \001(\0132\021.sysml.ConstraintR\005where\"\222\001\n\nC" + + "onstraint\022:\n\tprimitive\030\001 \001(\0132\032.sysml.Pri" + + "mitiveConstraintH\000R\tprimitive\022:\n\tcomposi" + + "te\030\002 \001(\0132\032.sysml.CompositeConstraintH\000R\t" + + "compositeB\014\n\nconstraint\"\227\001\n\023PrimitiveCon" + + "straint\022\030\n\007inverse\030\001 \001(\010R\007inverse\022\032\n\010pro" + + "perty\030\002 \001(\tR\010property\0224\n\010operator\030\003 \001(\0162" + + "\030.sysml.PrimitiveOperatorR\010operator\022\024\n\005v" + + "alue\030\004 \003(\tR\005value\"~\n\023CompositeConstraint" + + "\0224\n\010operator\030\001 \001(\0162\030.sysml.CompositeOper" + + "atorR\010operator\0221\n\nconstraint\030\002 \003(\0132\021.sys" + + "ml.ConstraintR\nconstraint\"\302\001\n\022QueryResul" + + "tElement\022\016\n\002id\030\001 \001(\tR\002id\022\022\n\004type\030\002 \001(\tR\004" + + "type\022I\n\nproperties\030\003 \003(\0132).sysml.QueryRe" + + "sultElement.PropertiesEntryR\nproperties\032" + + "=\n\017PropertiesEntry\022\020\n\003key\030\001 \001(\tR\003key\022\024\n\005" + + "value\030\002 \001(\tR\005value:\0028\001\"\220\001\n\nSweepRange\022\034\n" + + "\tparameter\030\001 \001(\tR\tparameter\022\"\n\005start\030\002 \001" + + "(\0132\014.sysml.ValueR\005start\022\036\n\003end\030\003 \001(\0132\014.s" + + "ysml.ValueR\003end\022 \n\004step\030\004 \001(\0132\014.sysml.Va" + + "lueR\004step\"\244\003\n\017RunSweepRequest\022\035\n\nmodel_h" + + "ash\030\001 \001(\tR\tmodelHash\022\033\n\tsymbol_id\030\002 \001(\tR" + + "\010symbolId\022*\n\021subject_symbol_id\030\003 \001(\tR\017su" + + "bjectSymbolId\022*\n\targuments\030\004 \003(\0132\014.sysml" + + ".ValueR\targuments\022S\n\017named_arguments\030\005 \003" + + "(\0132*.sysml.RunSweepRequest.NamedArgument" + + "sEntryR\016namedArguments\022)\n\006ranges\030\006 \003(\0132\021" + + ".sysml.SweepRangeR\006ranges\022\030\n\007samples\030\007 \001" + + "(\003R\007samples\022\022\n\004seed\030\010 \001(\004R\004seed\032O\n\023Named" + + "ArgumentsEntry\022\020\n\003key\030\001 \001(\tR\003key\022\"\n\005valu" + + "e\030\002 \001(\0132\014.sysml.ValueR\005value:\0028\001\"\210\002\n\010Swe" + + "epRow\022)\n\006inputs\030\001 \003(\0132\021.sysml.CalcOutput" + + "R\006inputs\022+\n\007outputs\030\002 \003(\0132\021.sysml.CalcOu" + + "tputR\007outputs\022*\n\010verdicts\030\003 \003(\0132\016.sysml." + + "VerdictR\010verdicts\022%\n\016elapsed_micros\030\004 \001(" + + "\003R\relapsedMicros\022\024\n\005error\030\005 \001(\tR\005error\022;" + + "\n\016failure_reason\030\006 \001(\0162\024.sysml.FailureRe" + + "asonR\rfailureReason\"\274\002\n\020RunSweepResponse" + + "\022#\n\004rows\030\001 \003(\0132\017.sysml.SweepRowR\004rows\022\036\n" + + "\nparameters\030\002 \003(\tR\nparameters\022\030\n\007sampled" + + "\030\003 \001(\010R\007sampled\022\022\n\004seed\030\004 \001(\004R\004seed\022\024\n\005e" + + "rror\030\005 \001(\tR\005error\0223\n\013diagnostics\030\006 \003(\0132\021" + + ".sysml.DiagnosticR\013diagnostics\022;\n\016failur" + + "e_reason\030\007 \001(\0162\024.sysml.FailureReasonR\rfa" + + "ilureReason\022-\n\tinstances\030\010 \003(\0132\017.sysml.I" + + "nstanceR\tinstances\"\214\001\n\027RunDocumentQueryR" + + "equest\022\035\n\nmodel_hash\030\001 \001(\tR\tmodelHash\022\031\n" + + "\010query_id\030\002 \001(\tR\007queryId\0227\n\010bindings\030\003 \003" + + "(\0132\033.sysml.DocumentQueryBindingR\010binding" + + "s\"b\n\024DocumentQueryBinding\022\034\n\tparameter\030\001" + + " \001(\tR\tparameter\022,\n\006values\030\002 \003(\0132\024.sysml." + + "DocumentValueR\006values\"\256\002\n\rDocumentValue\022" + + "\037\n\nelement_id\030\001 \001(\tH\000R\telementId\022#\n\014stri" + + "ng_value\030\002 \001(\tH\000R\013stringValue\022\035\n\tint_val" + + "ue\030\003 \001(\003H\000R\010intValue\022\037\n\nreal_value\030\004 \001(\001" + + "H\000R\trealValue\022\037\n\nbool_value\030\005 \001(\010H\000R\tboo" + + "lValue\022\034\n\010infinity\030\006 \001(\010H\000R\010infinity\022-\n\010" + + "quantity\030\010 \001(\0132\017.sysml.QuantityH\000R\010quant" + + "ity\022!\n\014element_type\030\007 \001(\tR\013elementTypeB\006" + + "\n\004kind\")\n\023DocumentQueryColumn\022\022\n\004name\030\001 " + + "\001(\tR\004name\"A\n\021DocumentQueryCell\022,\n\006values" + + "\030\001 \003(\0132\024.sysml.DocumentValueR\006values\"r\n\020" + + "DocumentQueryRow\022.\n\007element\030\001 \001(\0132\024.sysm" + + "l.DocumentValueR\007element\022.\n\005cells\030\002 \003(\0132" + + "\030.sysml.DocumentQueryCellR\005cells\"}\n\030RunD" + + "ocumentQueryResponse\0224\n\007columns\030\001 \003(\0132\032." + + "sysml.DocumentQueryColumnR\007columns\022+\n\004ro" + + "ws\030\002 \003(\0132\027.sysml.DocumentQueryRowR\004rows\"" + + "W\n\025RenderDocumentRequest\022\035\n\nmodel_hash\030\001" + + " \001(\tR\tmodelHash\022\037\n\013document_id\030\002 \001(\tR\ndo" + + "cumentId\"4\n\026RenderDocumentResponse\022\032\n\010ma" + + "rkdown\030\001 \001(\tR\010markdown*\223\001\n\rFailureReason" + + "\022\036\n\032FAILURE_REASON_UNSPECIFIED\020\000\022\035\n\031FAIL" + + "URE_REASON_EVALUATION\020\001\022\035\n\031FAILURE_REASO" + + "N_WRONG_KIND\020\002\022$\n FAILURE_REASON_AMBIGUO" + + "US_SUBJECT\020\003*\235\004\n\013EditFailure\022\034\n\030EDIT_FAI" + + "LURE_UNSPECIFIED\020\000\022\036\n\032EDIT_FAILURE_NO_OP" + + "ERATIONS\020\001\022\037\n\033EDIT_FAILURE_UNKNOWN_TARGE" + + "T\020\002\022!\n\035EDIT_FAILURE_AMBIGUOUS_TARGET\020\003\022\033" + + "\n\027EDIT_FAILURE_NOT_VALUED\020\004\022\036\n\032EDIT_FAIL" + + "URE_INVALID_VALUE\020\005\022\035\n\031EDIT_FAILURE_INVA" + + "LID_NAME\020\006\022\032\n\026EDIT_FAILURE_NOT_NAMED\020\007\022\"" + + "\n\036EDIT_FAILURE_RENAME_REFERENCED\020\010\022\"\n\036ED" + + "IT_FAILURE_OVERLAPPING_EDITS\020\t\022\037\n\033EDIT_F" + + "AILURE_RESULT_INVALID\020\n\022\036\n\032EDIT_FAILURE_" + + "OWNER_UNKNOWN\020\013\022$\n EDIT_FAILURE_OWNER_NO" + + "T_NAMESPACE\020\014\022\035\n\031EDIT_FAILURE_ILLEGAL_KI" + + "ND\020\r\022\"\n\036EDIT_FAILURE_MEMBER_NAME_TAKEN\020\016" + + "\022\"\n\036EDIT_FAILURE_DELETE_REFERENCED\020\017*\222\001\n" + + "\021PrimitiveOperator\022\"\n\036PRIMITIVE_OPERATOR" + + "_UNSPECIFIED\020\000\022\034\n\030PRIMITIVE_OPERATOR_EQU" + + "AL\020\001\022\036\n\032PRIMITIVE_OPERATOR_GREATER\020\002\022\033\n\027" + + "PRIMITIVE_OPERATOR_LESS\020\003*n\n\021CompositeOp" + + "erator\022\"\n\036COMPOSITE_OPERATOR_UNSPECIFIED" + + "\020\000\022\032\n\026COMPOSITE_OPERATOR_AND\020\001\022\031\n\025COMPOS" + + "ITE_OPERATOR_OR\020\0022\244\013\n\014SysMLService\022D\n\rGe" + + "tServerInfo\022\030.sysml.ServerInfoRequest\032\031." + + "sysml.ServerInfoResponse\022>\n\tParseFile\022\027." + + "sysml.ParseFileRequest\032\030.sysml.ParseFile" + + "Response\022G\n\014ParseSources\022\032.sysml.ParseSo" + + "urcesRequest\032\033.sysml.ParseSourcesRespons" + + "e\022;\n\tGetSymbol\022\027.sysml.GetSymbolRequest\032" + + "\025.sysml.SymbolResponse\022G\n\016GetDiagnostics" + + "\022\031.sysml.DiagnosticsRequest\032\032.sysml.Diag" + + "nosticsResponse\022;\n\010Evaluate\022\026.sysml.Eval" + + "uateRequest\032\027.sysml.EvaluateResponse\022D\n\013" + + "Instantiate\022\031.sysml.InstantiateRequest\032\032" + + ".sysml.InstantiateResponse\022J\n\rExecuteAct" + + "ion\022\033.sysml.ExecuteActionRequest\032\034.sysml" + + ".ExecuteActionResponse\022G\n\014ExecuteState\022\032" + + ".sysml.ExecuteStateRequest\032\033.sysml.Execu" + + "teStateResponse\0228\n\007Convert\022\025.sysml.Conve" + + "rtRequest\032\026.sysml.ConvertResponse\022A\n\nApp" + + "lyEdits\022\030.sysml.ApplyEditsRequest\032\031.sysm" + + "l.ApplyEditsResponse\022S\n\020VerifyConstraint" + + "\022\036.sysml.VerifyConstraintRequest\032\037.sysml" + + ".VerifyConstraintResponse\022V\n\021VerifyRequi" + + "rement\022\037.sysml.VerifyRequirementRequest\032" + + " .sysml.VerifyRequirementResponse\022Y\n\022Ver" + + "ifySatisfaction\022 .sysml.VerifySatisfacti" + + "onRequest\032!.sysml.VerifySatisfactionResp" + + "onse\022G\n\014EvaluateCalc\022\032.sysml.EvaluateCal" + + "cRequest\032\033.sysml.EvaluateCalcResponse\022D\n" + + "\013RunAnalysis\022\031.sysml.RunAnalysisRequest\032" + + "\032.sysml.RunAnalysisResponse\022;\n\010RunSweep\022" + + "\026.sysml.RunSweepRequest\032\027.sysml.RunSweep" + + "Response\0222\n\005Query\022\023.sysml.QueryRequest\032\024" + + ".sysml.QueryResponse\022S\n\020RunDocumentQuery", + "\022\036.sysml.RunDocumentQueryRequest\032\037.sysml" + + ".RunDocumentQueryResponse\022M\n\016RenderDocum" + + "ent\022\034.sysml.RenderDocumentRequest\032\035.sysm" + + "l.RenderDocumentResponseBJ\n\034org.openmbee" + + ".opensysml.protoP\001Z(github.com/Open-MBEE" + + "/OpenSysML/api/protob\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, @@ -1296,7 +1296,7 @@ public static void registerAllExtensions( internal_static_sysml_Diagnostic_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_sysml_Diagnostic_descriptor, - new java.lang.String[] { "Severity", "Message", "Span", }); + new java.lang.String[] { "Severity", "Message", "Span", "Code", }); internal_static_sysml_Span_descriptor = getDescriptor().getMessageType(60); internal_static_sysml_Span_fieldAccessorTable = new diff --git a/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/ApiIntegrationTest.java b/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/ApiIntegrationTest.java index 1e78196c1..e8240bd68 100644 --- a/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/ApiIntegrationTest.java +++ b/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/ApiIntegrationTest.java @@ -288,6 +288,13 @@ void aParseThatFindsErrorsReportsThemAsDiagnosticsRatherThanARefusal() { assertEquals(diagnostics, model.diagnostics()); } + @Test + void theServiceAdvertisesTheDiagnosticCodesItPopulates() { + assertTrue(connection.capabilities().has(Capabilities.DIAGNOSTIC_CODES)); + Model model = connection.parse("package P { part def W { part hub : Missing; } }"); + assertTrue(model.diagnostics().stream().anyMatch(d -> "unresolved".equals(d.code()))); + } + @Test void aJsonBodyAnswersWhatAProtobufBodyAnswers() { try (Connection json = diff --git a/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/PublicTypesTest.java b/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/PublicTypesTest.java index 6e98d16c0..90cd4748e 100644 --- a/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/PublicTypesTest.java +++ b/clients/java/opensysml-client/src/test/java/org/openmbee/opensysml/PublicTypesTest.java @@ -17,6 +17,7 @@ import java.util.Map; import java.util.Optional; import org.junit.jupiter.api.Test; +import org.openmbee.opensysml.internal.Protos; /** The public value types: immutable, comparable by value, and free of generated types. */ class PublicTypesTest { @@ -119,6 +120,27 @@ void diagnosticSeverityReadsTheWireName() { assertEquals(Diagnostic.Severity.UNKNOWN, Diagnostic.Severity.fromWireName("")); } + @Test + void diagnosticCarriesTheWireCode() { + List read = + Protos.diagnostics( + List.of( + org.openmbee.opensysml.proto.Diagnostic.newBuilder() + .setSeverity("info") + .setMessage("choice point: 2 steppable tokens") + .setCode("choice-point") + .build(), + org.openmbee.opensysml.proto.Diagnostic.newBuilder() + .setSeverity("error") + .setMessage("uncoded") + .build())); + assertEquals("choice-point", read.get(0).code()); + assertEquals("", read.get(1).code()); + assertThrows( + NullPointerException.class, + () -> new Diagnostic(Diagnostic.Severity.ERROR, "m", null, Optional.empty())); + } + @Test void aModelExceptionPreservesDiagnosticsWhenSerialized() throws Exception { List diagnostics = @@ -126,8 +148,9 @@ void aModelExceptionPreservesDiagnosticsWhenSerialized() throws Exception { new Diagnostic( Diagnostic.Severity.ERROR, "invalid model", + "unresolved", Optional.of(new Diagnostic.Span("model.sysml", 2, 3, 2, 8))), - new Diagnostic(Diagnostic.Severity.WARNING, "unlocated", Optional.empty())); + new Diagnostic(Diagnostic.Severity.WARNING, "unlocated", "", Optional.empty())); ModelException original = new ModelException("rejected", diagnostics); ByteArrayOutputStream bytes = new ByteArrayOutputStream(); diff --git a/clients/java/opensysml-conformance/src/main/java/org/openmbee/opensysml/conformance/Rendering.java b/clients/java/opensysml-conformance/src/main/java/org/openmbee/opensysml/conformance/Rendering.java index 8430d77c4..8166c373d 100644 --- a/clients/java/opensysml-conformance/src/main/java/org/openmbee/opensysml/conformance/Rendering.java +++ b/clients/java/opensysml-conformance/src/main/java/org/openmbee/opensysml/conformance/Rendering.java @@ -144,7 +144,8 @@ private static org.openmbee.opensysml.proto.Diagnostic diagnostic(Diagnostic dia org.openmbee.opensysml.proto.Diagnostic.Builder builder = org.openmbee.opensysml.proto.Diagnostic.newBuilder() .setSeverity(diagnostic.severity().wireName()) - .setMessage(diagnostic.message()); + .setMessage(diagnostic.message()) + .setCode(diagnostic.code()); diagnostic .span() .ifPresent( diff --git a/clients/node/README.md b/clients/node/README.md index d500b1af2..0c0e3aac5 100644 --- a/clients/node/README.md +++ b/clients/node/README.md @@ -214,7 +214,12 @@ try { ``` Source that does not parse is not a failure: `load`/`loads` return a model whose -`hasErrors` is true and whose `diagnostics` say where. Options that cannot work +`hasErrors` is true and whose `diagnostics` say where. Each `ModelDiagnostic` has +`severity`, `message`, `code` and an optional location; branch on `code` +(`"syntax"`, a validation code such as `"unresolved"`, `"choice-point"`, +`"guard-unevaluable"`; `""` when the service assigned none), not on the message +text. A service that populates `code` advertises `CAPABILITY_DIAGNOSTIC_CODES`; +without it every code is `""`. Options that cannot work (an encoding that is not one, a timeout that cannot elapse, `grpc` with `json`) are refused before a connection is opened or a service started. diff --git a/clients/node/src/core/capabilities.ts b/clients/node/src/core/capabilities.ts index 2b7ad68f1..85053090d 100644 --- a/clients/node/src/core/capabilities.ts +++ b/clients/node/src/core/capabilities.ts @@ -26,6 +26,8 @@ export const CAPABILITY_MEASUREMENT_REFS = "measurement_refs"; export const CAPABILITY_FUNCTION_VALUES = "function_values"; /** The unbounded value `*` as `Value.infinity`, rather than an unsupported null. */ export const CAPABILITY_INFINITY_VALUE = "infinity_value"; +/** `Diagnostic.code` is populated, so an empty code is a finding none was assigned. */ +export const CAPABILITY_DIAGNOSTIC_CODES = "diagnostic_codes"; /** `ParseFileRequest.language`, which declares the language of inline content. */ export const CAPABILITY_INLINE_LANGUAGE = "inline_language"; /** `ParseFileRequest.strict_conformance`. */ diff --git a/clients/node/src/core/errors.ts b/clients/node/src/core/errors.ts index 97f845333..daee94a95 100644 --- a/clients/node/src/core/errors.ts +++ b/clients/node/src/core/errors.ts @@ -85,6 +85,9 @@ export class ParseError extends OpenSysMLError { export interface ModelDiagnostic { severity: string; message: string; + /** What was found, stable across message wording (`"syntax"`, a validation code, + * `"choice-point"`, `"guard-unevaluable"`); `""` when the service assigned none. */ + code: string; file?: string; startLine?: number; startColumn?: number; diff --git a/clients/node/src/core/index.ts b/clients/node/src/core/index.ts index da1e56e26..d2703effe 100644 --- a/clients/node/src/core/index.ts +++ b/clients/node/src/core/index.ts @@ -25,6 +25,7 @@ export { CAPABILITY_APPLY_EDITS, CAPABILITY_COMPLEX_VALUES, CAPABILITY_CONVERT, + CAPABILITY_DIAGNOSTIC_CODES, CAPABILITY_ENUM_VALUES, CAPABILITY_EVALUATE_SUBJECT, CAPABILITY_FEATURE_VALUES, diff --git a/clients/node/src/core/model.ts b/clients/node/src/core/model.ts index ac307eaa7..e5aa9973f 100644 --- a/clients/node/src/core/model.ts +++ b/clients/node/src/core/model.ts @@ -477,6 +477,7 @@ function decodeDiagnostic(diagnostic: Diagnostic): ModelDiagnostic { return { severity: diagnostic.severity, message: diagnostic.message, + code: diagnostic.code, ...(span === undefined ? {} : { diff --git a/clients/node/src/generated/sysml_pb.ts b/clients/node/src/generated/sysml_pb.ts index 2079572ab..edcdc9e98 100644 --- a/clients/node/src/generated/sysml_pb.ts +++ b/clients/node/src/generated/sysml_pb.ts @@ -10,7 +10,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file sysml.proto. */ export const file_sysml: GenFile = /*@__PURE__*/ - fileDesc("CgtzeXNtbC5wcm90bxIFc3lzbWwi4gEKB1ZlcmRpY3QSDAoEa2luZBgBIAEoCRISCgplbGVtZW50X2lkGAIgASgJEg8KB2VsZW1lbnQYAyABKAkSDQoFaG9sZHMYBCABKAgSEQoJY29uZGl0aW9uGAUgASgJEhMKC2luc3RhbmNlX2lkGAYgASgDEhgKEGluc3RhbmNlX3R5cGVfaWQYByABKAkSDQoFZXJyb3IYCCABKAkSLAoOZmFpbHVyZV9yZWFzb24YCSABKA4yFC5zeXNtbC5GYWlsdXJlUmVhc29uEhYKDnJlcXVpcmVtZW50X2lkGAogASgJIlsKF1ZlcmlmeUNvbnN0cmFpbnRSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSEQoJc3ltYm9sX2lkGAIgASgJEhkKEXN1YmplY3Rfc3ltYm9sX2lkGAMgASgJIpYBChhWZXJpZnlDb25zdHJhaW50UmVzcG9uc2USHwoHdmVyZGljdBgBIAEoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAIgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljIlwKGFZlcmlmeVJlcXVpcmVtZW50UmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCRIZChFzdWJqZWN0X3N5bWJvbF9pZBgDIAEoCSJtChNWZXJpZmljYXRpb25WZXJkaWN0Eg8KB2Nhc2VfaWQYASABKAkSDAoEa2luZBgCIAEoCRIOCgZkZXRhaWwYAyABKAkSDwoHc3ViY2FzZRgEIAEoCBIWCg5yZXF1aXJlbWVudF9pZBgFIAEoCSLSAQoZVmVyaWZ5UmVxdWlyZW1lbnRSZXNwb25zZRIfCgd2ZXJkaWN0GAEgASgLMg4uc3lzbWwuVmVyZGljdBIiCglpbnN0YW5jZXMYAiADKAsyDy5zeXNtbC5JbnN0YW5jZRINCgVlcnJvchgDIAEoCRImCgtkaWFnbm9zdGljcxgEIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSOQoVdmVyaWZpY2F0aW9uX3ZlcmRpY3RzGAUgAygLMhouc3lzbWwuVmVyaWZpY2F0aW9uVmVyZGljdCJCChlWZXJpZnlTYXRpc2ZhY3Rpb25SZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSEQoJc3ltYm9sX2lkGAIgASgJIoICChpWZXJpZnlTYXRpc2ZhY3Rpb25SZXNwb25zZRIgCgh2ZXJkaWN0cxgBIAMoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAIgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljEiwKDmZhaWx1cmVfcmVhc29uGAUgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbhI5ChV2ZXJpZmljYXRpb25fdmVyZGljdHMYBiADKAsyGi5zeXNtbC5WZXJpZmljYXRpb25WZXJkaWN0Il0KE0V2YWx1YXRlQ2FsY1JlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIRCglzeW1ib2xfaWQYAiABKAkSHwoJYXJndW1lbnRzGAMgAygLMgwuc3lzbWwuVmFsdWUivQEKFEV2YWx1YXRlQ2FsY1Jlc3BvbnNlEhwKBnJlc3VsdBgBIAEoCzIMLnN5c21sLlZhbHVlEiIKB291dHB1dHMYAiADKAsyES5zeXNtbC5DYWxjT3V0cHV0Eg0KBWVycm9yGAMgASgJEiYKC2RpYWdub3N0aWNzGAQgAygLMhEuc3lzbWwuRGlhZ25vc3RpYxIsCg5mYWlsdXJlX3JlYXNvbhgFIAEoDjIULnN5c21sLkZhaWx1cmVSZWFzb24iNwoKQ2FsY091dHB1dBIMCgRuYW1lGAEgASgJEhsKBXZhbHVlGAIgASgLMgwuc3lzbWwuVmFsdWUihAIKElJ1bkFuYWx5c2lzUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCRIZChFzdWJqZWN0X3N5bWJvbF9pZBgDIAEoCRIfCglhcmd1bWVudHMYBCADKAsyDC5zeXNtbC5WYWx1ZRJGCg9uYW1lZF9hcmd1bWVudHMYBSADKAsyLS5zeXNtbC5SdW5BbmFseXNpc1JlcXVlc3QuTmFtZWRBcmd1bWVudHNFbnRyeRpDChNOYW1lZEFyZ3VtZW50c0VudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASKfAgoTUnVuQW5hbHlzaXNSZXNwb25zZRIiCgdvdXRwdXRzGAEgAygLMhEuc3lzbWwuQ2FsY091dHB1dBIgCgh2ZXJkaWN0cxgCIAMoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAMgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYBCABKAkSJgoLZGlhZ25vc3RpY3MYBSADKAsyES5zeXNtbC5EaWFnbm9zdGljEiwKDmZhaWx1cmVfcmVhc29uGAYgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbhI5ChV2ZXJpZmljYXRpb25fdmVyZGljdHMYByADKAsyGi5zeXNtbC5WZXJpZmljYXRpb25WZXJkaWN0IowBChBQYXJzZUZpbGVSZXF1ZXN0EhMKCWZpbGVfcGF0aBgBIAEoCUgAEhEKB2NvbnRlbnQYAiABKAlIABIYCgxjb250ZW50X2hhc2gYAyABKAlCAhgBEhAKCGxhbmd1YWdlGAQgASgJEhoKEnN0cmljdF9jb25mb3JtYW5jZRgFIAEoCEIICgZzb3VyY2UiYgoOU291cmNlRG9jdW1lbnQSEwoJZmlsZV9wYXRoGAEgASgJSAASEQoHY29udGVudBgCIAEoCUgAEhAKCGxhbmd1YWdlGAMgASgJEgwKBG5hbWUYBCABKAlCCAoGc291cmNlIlsKE1BhcnNlU291cmNlc1JlcXVlc3QSKAoJZG9jdW1lbnRzGAEgAygLMhUuc3lzbWwuU291cmNlRG9jdW1lbnQSGgoSc3RyaWN0X2NvbmZvcm1hbmNlGAIgASgIIoMBChRQYXJzZVNvdXJjZXNSZXNwb25zZRISCgptb2RlbF9oYXNoGAEgASgJEiAKBXJvb3RzGAIgAygLMhEuc3lzbWwuU3ltYm9sSW5mbxImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSDQoFZXJyb3IYBCABKAkifwoRUGFyc2VGaWxlUmVzcG9uc2USEgoKbW9kZWxfaGFzaBgBIAEoCRIfCgRyb290GAIgASgLMhEuc3lzbWwuU3ltYm9sSW5mbxImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSDQoFZXJyb3IYBCABKAkiOQoQR2V0U3ltYm9sUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCSJCCg5TeW1ib2xSZXNwb25zZRIhCgZzeW1ib2wYASABKAsyES5zeXNtbC5TeW1ib2xJbmZvEg0KBWVycm9yGAIgASgJIigKEkRpYWdub3N0aWNzUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJIkwKE0RpYWdub3N0aWNzUmVzcG9uc2USJgoLZGlhZ25vc3RpY3MYASADKAsyES5zeXNtbC5EaWFnbm9zdGljEg0KBWVycm9yGAIgASgJIm8KD0V2YWx1YXRlUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhIKCmV4cHJlc3Npb24YAiABKAkSGQoRY29udGV4dF9zeW1ib2xfaWQYAyABKAkSGQoRc3ViamVjdF9zeW1ib2xfaWQYBCABKAkiZwoQRXZhbHVhdGVSZXNwb25zZRIcCgZyZXN1bHQYASABKAsyDC5zeXNtbC5WYWx1ZRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMiwgEKCEluc3RhbmNlEgoKAmlkGAEgASgDEhYKDnR5cGVfc3ltYm9sX2lkGAIgASgJEjoKDmZlYXR1cmVfdmFsdWVzGAQgAygLMiIuc3lzbWwuSW5zdGFuY2UuRmVhdHVyZVZhbHVlc0VudHJ5GkkKEkZlYXR1cmVWYWx1ZXNFbnRyeRILCgNrZXkYASABKAkSIgoFdmFsdWUYAiABKAsyEy5zeXNtbC5GZWF0dXJlVmFsdWU6AjgBSgQIAxAEUgVzbG90cyKEAQoMRmVhdHVyZVZhbHVlEhQKDGZlYXR1cmVfbmFtZRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlEhwKBnZhbHVlcxgDIAMoCzIMLnN5c21sLlZhbHVlEhQKDG1hdGVyaWFsaXplZBgEIAEoCBINCgVlcnJvchgFIAEoCSI7ChJJbnN0YW50aWF0ZVJlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIRCglzeW1ib2xfaWQYAiABKAkikwEKE0luc3RhbnRpYXRlUmVzcG9uc2USIQoIaW5zdGFuY2UYASABKAsyDy5zeXNtbC5JbnN0YW5jZRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSIgoJaW5zdGFuY2VzGAQgAygLMg8uc3lzbWwuSW5zdGFuY2UiugEKFEV4ZWN1dGVBY3Rpb25SZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSGAoQYWN0aW9uX3N5bWJvbF9pZBgCIAEoCRI3CgZpbnB1dHMYAyADKAsyJy5zeXNtbC5FeGVjdXRlQWN0aW9uUmVxdWVzdC5JbnB1dHNFbnRyeRo7CgtJbnB1dHNFbnRyeRILCgNrZXkYASABKAkSGwoFdmFsdWUYAiABKAsyDC5zeXNtbC5WYWx1ZToCOAEiyAEKFUV4ZWN1dGVBY3Rpb25SZXNwb25zZRI6CgdvdXRwdXRzGAEgAygLMikuc3lzbWwuRXhlY3V0ZUFjdGlvblJlc3BvbnNlLk91dHB1dHNFbnRyeRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMaPAoMT3V0cHV0c0VudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASJaChNFeGVjdXRlU3RhdGVSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSHwoXc3RhdGVfbWFjaGluZV9zeW1ib2xfaWQYAiABKAkSDgoGZXZlbnRzGAMgAygJIu4BChRFeGVjdXRlU3RhdGVSZXNwb25zZRIWCg5zdGF0ZXNfdmlzaXRlZBgBIAMoCRJECg1maW5hbF9jb250ZXh0GAIgAygLMi0uc3lzbWwuRXhlY3V0ZVN0YXRlUmVzcG9uc2UuRmluYWxDb250ZXh0RW50cnkSDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljGkEKEUZpbmFsQ29udGV4dEVudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASKgAQoOQ29udmVydFJlcXVlc3QSEwoJZmlsZV9wYXRoGAEgASgJSAASEQoHY29udGVudBgCIAEoCUgAEhQKCm1vZGVsX2hhc2gYBiABKAlIABITCgtmcm9tX2Zvcm1hdBgDIAEoCRIRCgl0b19mb3JtYXQYBCABKAkSHgoWdG9sZXJhdGVfc3ludGF4X2Vycm9ycxgFIAEoCEIICgZzb3VyY2UitAEKD0NvbnZlcnRSZXNwb25zZRIPCgdjb250ZW50GAEgASgJEhMKC2Zyb21fZm9ybWF0GAIgASgJEhEKCXRvX2Zvcm1hdBgDIAEoCRINCgVlcnJvchgEIAEoCRImCgtkaWFnbm9zdGljcxgFIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSFAoMZXhwZXJpbWVudGFsGAYgASgIEhsKE2V4cGVyaW1lbnRhbF9ub3RpY2UYByABKAkiUQoRQXBwbHlFZGl0c1JlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIoCgpvcGVyYXRpb25zGAIgAygLMhQuc3lzbWwuRWRpdE9wZXJhdGlvbiK8AQoNRWRpdE9wZXJhdGlvbhIoCglzZXRfdmFsdWUYASABKAsyEy5zeXNtbC5TZXRWYWx1ZUVkaXRIABIjCgZyZW5hbWUYAiABKAsyES5zeXNtbC5SZW5hbWVFZGl0SAASKgoKYWRkX21lbWJlchgDIAEoCzIULnN5c21sLkFkZE1lbWJlckVkaXRIABIjCgZkZWxldGUYBCABKAsyES5zeXNtbC5EZWxldGVFZGl0SABCCwoJb3BlcmF0aW9uIoIBCg1BZGRNZW1iZXJFZGl0Eg0KBW93bmVyGAEgASgJEgwKBGtpbmQYAiABKAkSDAoEbmFtZRgDIAEoCRIMCgR0eXBlGAQgASgJEhQKDG11bHRpcGxpY2l0eRgFIAEoCRINCgV2YWx1ZRgGIAEoCRITCgtzcGVjaWFsaXplcxgHIAMoCSItCgpEZWxldGVFZGl0Eg4KBnRhcmdldBgBIAEoCRIPCgdjYXNjYWRlGAIgASgIIi0KDFNldFZhbHVlRWRpdBIOCgZ0YXJnZXQYASABKAkSDQoFdmFsdWUYAiABKAkiLgoKUmVuYW1lRWRpdBIOCgZ0YXJnZXQYASABKAkSEAoIbmV3X25hbWUYAiABKAkiwgEKEkFwcGx5RWRpdHNSZXNwb25zZRIPCgdjb250ZW50GAEgASgJEiMKB2FwcGxpZWQYAiADKAsyEi5zeXNtbC5BcHBsaWVkRWRpdBINCgVlcnJvchgDIAEoCRIjCgdmYWlsdXJlGAQgASgOMhIuc3lzbWwuRWRpdEZhaWx1cmUSJgoLZGlhZ25vc3RpY3MYBSADKAsyES5zeXNtbC5EaWFnbm9zdGljEhoKEnJlZmVycmluZ19lbGVtZW50cxgGIAMoCSJ6CgtBcHBsaWVkRWRpdBIXCg9vcGVyYXRpb25faW5kZXgYASABKAUSDgoGdGFyZ2V0GAIgASgJEg4KBm9mZnNldBgDIAEoBRIOCgZsZW5ndGgYBCABKAUSEAoIb2xkX3RleHQYBSABKAkSEAoIbmV3X3RleHQYBiABKAki/QIKClN5bWJvbEluZm8SCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIMCgRraW5kGAMgASgJEjEKCG1ldGFkYXRhGAQgAygLMh8uc3lzbWwuU3ltYm9sSW5mby5NZXRhZGF0YUVudHJ5EhEKCWNoaWxkX2lkcxgFIAMoCRIoCgphdHRyaWJ1dGVzGAYgAygLMhQuc3lzbWwuQXR0cmlidXRlSW5mbxIiCgl0eXBlX2luZm8YByABKAsyDy5zeXNtbC5UeXBlSW5mbxItCgxtdWx0aXBsaWNpdHkYCCABKAsyFy5zeXNtbC5NdWx0aXBsaWNpdHlJbmZvEi4KD3NwZWNpYWxpemF0aW9ucxgJIAMoCzIVLnN5c21sLlNwZWNpYWxpemF0aW9uEiMKG3dpdGhoZWxkX2xpYnJhcnlfYXR0cmlidXRlcxgKIAEoBRovCg1NZXRhZGF0YUVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEiWAoOU3BlY2lhbGl6YXRpb24SDAoEa2luZBgBIAEoCRIQCghkZWNsYXJlZBgCIAEoCRIRCgl0YXJnZXRfaWQYAyABKAkSEwoLdGFyZ2V0X2tpbmQYBCABKAkilQEKCFR5cGVJbmZvEhAKCGRlY2xhcmVkGAEgASgJEhMKC3Jlc29sdmVkX2lkGAIgASgJEhUKDXJlc29sdmVkX2tpbmQYAyABKAkSEQoJcHJpbWl0aXZlGAQgASgJEhgKEHByaW1pdGl2ZV9zb3VyY2UYBSABKAkSEAoIcXVhbnRpdHkYBiABKAgSDAoEdW5pdBgHIAEoCSIwChBNdWx0aXBsaWNpdHlJbmZvEg0KBWxvd2VyGAEgASgJEg0KBXVwcGVyGAIgASgJIlYKDUF0dHJpYnV0ZUluZm8SDAoEbmFtZRgBIAEoCRIMCgR0eXBlGAIgASgJEhsKBXZhbHVlGAMgASgLMgwuc3lzbWwuVmFsdWUSDAoEdW5pdBgEIAEoCSKbBAoFVmFsdWUSEwoJaW50X3ZhbHVlGAEgASgDSAASFAoKcmVhbF92YWx1ZRgCIAEoAUgAEhQKCmJvb2xfdmFsdWUYAyABKAhIABIWCgxzdHJpbmdfdmFsdWUYBCABKAlIABIVCgtpbnN0YW5jZV9pZBgFIAEoA0gAEigKCHNlcXVlbmNlGAYgASgLMhQuc3lzbWwuVmFsdWVTZXF1ZW5jZUgAEg4KBG51bGwYByABKAlIABIjCghxdWFudGl0eRgIIAEoCzIPLnN5c21sLlF1YW50aXR5SAASKgoMZW51bV9saXRlcmFsGAkgASgLMhIuc3lzbWwuRW51bUxpdGVyYWxIABIPCgV1bnNldBgKIAEoCEgAEiEKB2NvbXBsZXgYCyABKAsyDi5zeXNtbC5Db21wbGV4SAASHQoFYXJyYXkYDCABKAsyDC5zeXNtbC5BcnJheUgAEh8KBnZlY3RvchgNIAEoCzINLnN5c21sLlZlY3RvckgAEjAKD3ZlY3Rvcl9xdWFudGl0eRgOIAEoCzIVLnN5c21sLlZlY3RvclF1YW50aXR5SAASMAoPbWVhc3VyZW1lbnRfcmVmGA8gASgLMhUuc3lzbWwuTWVhc3VyZW1lbnRSZWZIABISCghpbmZpbml0eRgQIAEoCEgAEiMKCGZ1bmN0aW9uGBEgASgLMg8uc3lzbWwuRnVuY3Rpb25IAEIGCgRraW5kIiwKCEZ1bmN0aW9uEg8KB2NhbGNfaWQYASABKAkSDwoHc2VsZl9pZBgCIAEoAyI7CgVBcnJheRISCgpkaW1lbnNpb25zGAEgAygDEh4KCGVsZW1lbnRzGAIgAygLMgwuc3lzbWwuVmFsdWUiKgoGVmVjdG9yEiAKCmNvbXBvbmVudHMYASADKAsyDC5zeXNtbC5WYWx1ZSI1Cg5WZWN0b3JRdWFudGl0eRIjCgpjb21wb25lbnRzGAEgAygLMg8uc3lzbWwuUXVhbnRpdHkiKgoHQ29tcGxleBIMCgRyZWFsGAEgASgBEhEKCWltYWdpbmFyeRgCIAEoASJHCgtFbnVtTGl0ZXJhbBISCgpsaXRlcmFsX2lkGAEgASgJEhYKDmVudW1lcmF0aW9uX2lkGAIgASgJEgwKBG5hbWUYAyABKAkiLwoNVmFsdWVTZXF1ZW5jZRIeCghlbGVtZW50cxgBIAMoCzIMLnN5c21sLlZhbHVlInwKCFF1YW50aXR5EhcKDWludF9tYWduaXR1ZGUYASABKANIABIYCg5yZWFsX21hZ25pdHVkZRgCIAEoAUgAEgwKBHVuaXQYAyABKAkSIgoJdW5pdF90ZXJtGAQgASgLMg8uc3lzbWwuVW5pdFRlcm1CCwoJbWFnbml0dWRlIlMKDk1lYXN1cmVtZW50UmVmEgwKBHVuaXQYASABKAkSIgoJdW5pdF90ZXJtGAIgASgLMg8uc3lzbWwuVW5pdFRlcm0SDwoHdW5pdF9pZBgDIAEoCSJUCghVbml0VGVybRIRCglzY2FsZV9udW0YASABKAESEQoJc2NhbGVfZGVuGAIgASgBEiIKB2ZhY3RvcnMYAyADKAsyES5zeXNtbC5Vbml0RmFjdG9yIi8KClVuaXRGYWN0b3ISDwoHdW5pdF9pZBgBIAEoCRIQCghleHBvbmVudBgCIAEoASJKCgpEaWFnbm9zdGljEhAKCHNldmVyaXR5GAEgASgJEg8KB21lc3NhZ2UYAiABKAkSGQoEc3BhbhgDIAEoCzILLnN5c21sLlNwYW4iXgoEU3BhbhIMCgRmaWxlGAEgASgJEhIKCnN0YXJ0X2xpbmUYAiABKAUSEQoJc3RhcnRfY29sGAMgASgFEhAKCGVuZF9saW5lGAQgASgFEg8KB2VuZF9jb2wYBSABKAUiEwoRU2VydmVySW5mb1JlcXVlc3QiOwoSU2VydmVySW5mb1Jlc3BvbnNlEg8KB3ZlcnNpb24YASABKAkSFAoMY2FwYWJpbGl0aWVzGAIgAygJIlMKDFF1ZXJ5UmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhsKBXF1ZXJ5GAIgASgLMgwuc3lzbWwuUXVlcnkSEgoKb3NsY19xdWVyeRgDIAEoCSI8Cg1RdWVyeVJlc3BvbnNlEisKCGVsZW1lbnRzGAEgAygLMhkuc3lzbWwuUXVlcnlSZXN1bHRFbGVtZW50IkgKBVF1ZXJ5Eg0KBXNjb3BlGAEgAygJEg4KBnNlbGVjdBgCIAMoCRIgCgV3aGVyZRgDIAEoCzIRLnN5c21sLkNvbnN0cmFpbnQifAoKQ29uc3RyYWludBIvCglwcmltaXRpdmUYASABKAsyGi5zeXNtbC5QcmltaXRpdmVDb25zdHJhaW50SAASLwoJY29tcG9zaXRlGAIgASgLMhouc3lzbWwuQ29tcG9zaXRlQ29uc3RyYWludEgAQgwKCmNvbnN0cmFpbnQicwoTUHJpbWl0aXZlQ29uc3RyYWludBIPCgdpbnZlcnNlGAEgASgIEhAKCHByb3BlcnR5GAIgASgJEioKCG9wZXJhdG9yGAMgASgOMhguc3lzbWwuUHJpbWl0aXZlT3BlcmF0b3ISDQoFdmFsdWUYBCADKAkiaAoTQ29tcG9zaXRlQ29uc3RyYWludBIqCghvcGVyYXRvchgBIAEoDjIYLnN5c21sLkNvbXBvc2l0ZU9wZXJhdG9yEiUKCmNvbnN0cmFpbnQYAiADKAsyES5zeXNtbC5Db25zdHJhaW50IqABChJRdWVyeVJlc3VsdEVsZW1lbnQSCgoCaWQYASABKAkSDAoEdHlwZRgCIAEoCRI9Cgpwcm9wZXJ0aWVzGAMgAygLMikuc3lzbWwuUXVlcnlSZXN1bHRFbGVtZW50LlByb3BlcnRpZXNFbnRyeRoxCg9Qcm9wZXJ0aWVzRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ASJzCgpTd2VlcFJhbmdlEhEKCXBhcmFtZXRlchgBIAEoCRIbCgVzdGFydBgCIAEoCzIMLnN5c21sLlZhbHVlEhkKA2VuZBgDIAEoCzIMLnN5c21sLlZhbHVlEhoKBHN0ZXAYBCABKAsyDC5zeXNtbC5WYWx1ZSLAAgoPUnVuU3dlZXBSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSEQoJc3ltYm9sX2lkGAIgASgJEhkKEXN1YmplY3Rfc3ltYm9sX2lkGAMgASgJEh8KCWFyZ3VtZW50cxgEIAMoCzIMLnN5c21sLlZhbHVlEkMKD25hbWVkX2FyZ3VtZW50cxgFIAMoCzIqLnN5c21sLlJ1blN3ZWVwUmVxdWVzdC5OYW1lZEFyZ3VtZW50c0VudHJ5EiEKBnJhbmdlcxgGIAMoCzIRLnN5c21sLlN3ZWVwUmFuZ2USDwoHc2FtcGxlcxgHIAEoAxIMCgRzZWVkGAggASgEGkMKE05hbWVkQXJndW1lbnRzRW50cnkSCwoDa2V5GAEgASgJEhsKBXZhbHVlGAIgASgLMgwuc3lzbWwuVmFsdWU6AjgBIsgBCghTd2VlcFJvdxIhCgZpbnB1dHMYASADKAsyES5zeXNtbC5DYWxjT3V0cHV0EiIKB291dHB1dHMYAiADKAsyES5zeXNtbC5DYWxjT3V0cHV0EiAKCHZlcmRpY3RzGAMgAygLMg4uc3lzbWwuVmVyZGljdBIWCg5lbGFwc2VkX21pY3JvcxgEIAEoAxINCgVlcnJvchgFIAEoCRIsCg5mYWlsdXJlX3JlYXNvbhgGIAEoDjIULnN5c21sLkZhaWx1cmVSZWFzb24i7QEKEFJ1blN3ZWVwUmVzcG9uc2USHQoEcm93cxgBIAMoCzIPLnN5c21sLlN3ZWVwUm93EhIKCnBhcmFtZXRlcnMYAiADKAkSDwoHc2FtcGxlZBgDIAEoCBIMCgRzZWVkGAQgASgEEg0KBWVycm9yGAUgASgJEiYKC2RpYWdub3N0aWNzGAYgAygLMhEuc3lzbWwuRGlhZ25vc3RpYxIsCg5mYWlsdXJlX3JlYXNvbhgHIAEoDjIULnN5c21sLkZhaWx1cmVSZWFzb24SIgoJaW5zdGFuY2VzGAggAygLMg8uc3lzbWwuSW5zdGFuY2UibgoXUnVuRG9jdW1lbnRRdWVyeVJlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIQCghxdWVyeV9pZBgCIAEoCRItCghiaW5kaW5ncxgDIAMoCzIbLnN5c21sLkRvY3VtZW50UXVlcnlCaW5kaW5nIk8KFERvY3VtZW50UXVlcnlCaW5kaW5nEhEKCXBhcmFtZXRlchgBIAEoCRIkCgZ2YWx1ZXMYAiADKAsyFC5zeXNtbC5Eb2N1bWVudFZhbHVlItUBCg1Eb2N1bWVudFZhbHVlEhQKCmVsZW1lbnRfaWQYASABKAlIABIWCgxzdHJpbmdfdmFsdWUYAiABKAlIABITCglpbnRfdmFsdWUYAyABKANIABIUCgpyZWFsX3ZhbHVlGAQgASgBSAASFAoKYm9vbF92YWx1ZRgFIAEoCEgAEhIKCGluZmluaXR5GAYgASgISAASIwoIcXVhbnRpdHkYCCABKAsyDy5zeXNtbC5RdWFudGl0eUgAEhQKDGVsZW1lbnRfdHlwZRgHIAEoCUIGCgRraW5kIiMKE0RvY3VtZW50UXVlcnlDb2x1bW4SDAoEbmFtZRgBIAEoCSI5ChFEb2N1bWVudFF1ZXJ5Q2VsbBIkCgZ2YWx1ZXMYASADKAsyFC5zeXNtbC5Eb2N1bWVudFZhbHVlImIKEERvY3VtZW50UXVlcnlSb3cSJQoHZWxlbWVudBgBIAEoCzIULnN5c21sLkRvY3VtZW50VmFsdWUSJwoFY2VsbHMYAiADKAsyGC5zeXNtbC5Eb2N1bWVudFF1ZXJ5Q2VsbCJuChhSdW5Eb2N1bWVudFF1ZXJ5UmVzcG9uc2USKwoHY29sdW1ucxgBIAMoCzIaLnN5c21sLkRvY3VtZW50UXVlcnlDb2x1bW4SJQoEcm93cxgCIAMoCzIXLnN5c21sLkRvY3VtZW50UXVlcnlSb3ciQAoVUmVuZGVyRG9jdW1lbnRSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSEwoLZG9jdW1lbnRfaWQYAiABKAkiKgoWUmVuZGVyRG9jdW1lbnRSZXNwb25zZRIQCghtYXJrZG93bhgBIAEoCSqTAQoNRmFpbHVyZVJlYXNvbhIeChpGQUlMVVJFX1JFQVNPTl9VTlNQRUNJRklFRBAAEh0KGUZBSUxVUkVfUkVBU09OX0VWQUxVQVRJT04QARIdChlGQUlMVVJFX1JFQVNPTl9XUk9OR19LSU5EEAISJAogRkFJTFVSRV9SRUFTT05fQU1CSUdVT1VTX1NVQkpFQ1QQAyqdBAoLRWRpdEZhaWx1cmUSHAoYRURJVF9GQUlMVVJFX1VOU1BFQ0lGSUVEEAASHgoaRURJVF9GQUlMVVJFX05PX09QRVJBVElPTlMQARIfChtFRElUX0ZBSUxVUkVfVU5LTk9XTl9UQVJHRVQQAhIhCh1FRElUX0ZBSUxVUkVfQU1CSUdVT1VTX1RBUkdFVBADEhsKF0VESVRfRkFJTFVSRV9OT1RfVkFMVUVEEAQSHgoaRURJVF9GQUlMVVJFX0lOVkFMSURfVkFMVUUQBRIdChlFRElUX0ZBSUxVUkVfSU5WQUxJRF9OQU1FEAYSGgoWRURJVF9GQUlMVVJFX05PVF9OQU1FRBAHEiIKHkVESVRfRkFJTFVSRV9SRU5BTUVfUkVGRVJFTkNFRBAIEiIKHkVESVRfRkFJTFVSRV9PVkVSTEFQUElOR19FRElUUxAJEh8KG0VESVRfRkFJTFVSRV9SRVNVTFRfSU5WQUxJRBAKEh4KGkVESVRfRkFJTFVSRV9PV05FUl9VTktOT1dOEAsSJAogRURJVF9GQUlMVVJFX09XTkVSX05PVF9OQU1FU1BBQ0UQDBIdChlFRElUX0ZBSUxVUkVfSUxMRUdBTF9LSU5EEA0SIgoeRURJVF9GQUlMVVJFX01FTUJFUl9OQU1FX1RBS0VOEA4SIgoeRURJVF9GQUlMVVJFX0RFTEVURV9SRUZFUkVOQ0VEEA8qkgEKEVByaW1pdGl2ZU9wZXJhdG9yEiIKHlBSSU1JVElWRV9PUEVSQVRPUl9VTlNQRUNJRklFRBAAEhwKGFBSSU1JVElWRV9PUEVSQVRPUl9FUVVBTBABEh4KGlBSSU1JVElWRV9PUEVSQVRPUl9HUkVBVEVSEAISGwoXUFJJTUlUSVZFX09QRVJBVE9SX0xFU1MQAypuChFDb21wb3NpdGVPcGVyYXRvchIiCh5DT01QT1NJVEVfT1BFUkFUT1JfVU5TUEVDSUZJRUQQABIaChZDT01QT1NJVEVfT1BFUkFUT1JfQU5EEAESGQoVQ09NUE9TSVRFX09QRVJBVE9SX09SEAIypAsKDFN5c01MU2VydmljZRJECg1HZXRTZXJ2ZXJJbmZvEhguc3lzbWwuU2VydmVySW5mb1JlcXVlc3QaGS5zeXNtbC5TZXJ2ZXJJbmZvUmVzcG9uc2USPgoJUGFyc2VGaWxlEhcuc3lzbWwuUGFyc2VGaWxlUmVxdWVzdBoYLnN5c21sLlBhcnNlRmlsZVJlc3BvbnNlEkcKDFBhcnNlU291cmNlcxIaLnN5c21sLlBhcnNlU291cmNlc1JlcXVlc3QaGy5zeXNtbC5QYXJzZVNvdXJjZXNSZXNwb25zZRI7CglHZXRTeW1ib2wSFy5zeXNtbC5HZXRTeW1ib2xSZXF1ZXN0GhUuc3lzbWwuU3ltYm9sUmVzcG9uc2USRwoOR2V0RGlhZ25vc3RpY3MSGS5zeXNtbC5EaWFnbm9zdGljc1JlcXVlc3QaGi5zeXNtbC5EaWFnbm9zdGljc1Jlc3BvbnNlEjsKCEV2YWx1YXRlEhYuc3lzbWwuRXZhbHVhdGVSZXF1ZXN0Ghcuc3lzbWwuRXZhbHVhdGVSZXNwb25zZRJECgtJbnN0YW50aWF0ZRIZLnN5c21sLkluc3RhbnRpYXRlUmVxdWVzdBoaLnN5c21sLkluc3RhbnRpYXRlUmVzcG9uc2USSgoNRXhlY3V0ZUFjdGlvbhIbLnN5c21sLkV4ZWN1dGVBY3Rpb25SZXF1ZXN0Ghwuc3lzbWwuRXhlY3V0ZUFjdGlvblJlc3BvbnNlEkcKDEV4ZWN1dGVTdGF0ZRIaLnN5c21sLkV4ZWN1dGVTdGF0ZVJlcXVlc3QaGy5zeXNtbC5FeGVjdXRlU3RhdGVSZXNwb25zZRI4CgdDb252ZXJ0EhUuc3lzbWwuQ29udmVydFJlcXVlc3QaFi5zeXNtbC5Db252ZXJ0UmVzcG9uc2USQQoKQXBwbHlFZGl0cxIYLnN5c21sLkFwcGx5RWRpdHNSZXF1ZXN0Ghkuc3lzbWwuQXBwbHlFZGl0c1Jlc3BvbnNlElMKEFZlcmlmeUNvbnN0cmFpbnQSHi5zeXNtbC5WZXJpZnlDb25zdHJhaW50UmVxdWVzdBofLnN5c21sLlZlcmlmeUNvbnN0cmFpbnRSZXNwb25zZRJWChFWZXJpZnlSZXF1aXJlbWVudBIfLnN5c21sLlZlcmlmeVJlcXVpcmVtZW50UmVxdWVzdBogLnN5c21sLlZlcmlmeVJlcXVpcmVtZW50UmVzcG9uc2USWQoSVmVyaWZ5U2F0aXNmYWN0aW9uEiAuc3lzbWwuVmVyaWZ5U2F0aXNmYWN0aW9uUmVxdWVzdBohLnN5c21sLlZlcmlmeVNhdGlzZmFjdGlvblJlc3BvbnNlEkcKDEV2YWx1YXRlQ2FsYxIaLnN5c21sLkV2YWx1YXRlQ2FsY1JlcXVlc3QaGy5zeXNtbC5FdmFsdWF0ZUNhbGNSZXNwb25zZRJECgtSdW5BbmFseXNpcxIZLnN5c21sLlJ1bkFuYWx5c2lzUmVxdWVzdBoaLnN5c21sLlJ1bkFuYWx5c2lzUmVzcG9uc2USOwoIUnVuU3dlZXASFi5zeXNtbC5SdW5Td2VlcFJlcXVlc3QaFy5zeXNtbC5SdW5Td2VlcFJlc3BvbnNlEjIKBVF1ZXJ5EhMuc3lzbWwuUXVlcnlSZXF1ZXN0GhQuc3lzbWwuUXVlcnlSZXNwb25zZRJTChBSdW5Eb2N1bWVudFF1ZXJ5Eh4uc3lzbWwuUnVuRG9jdW1lbnRRdWVyeVJlcXVlc3QaHy5zeXNtbC5SdW5Eb2N1bWVudFF1ZXJ5UmVzcG9uc2USTQoOUmVuZGVyRG9jdW1lbnQSHC5zeXNtbC5SZW5kZXJEb2N1bWVudFJlcXVlc3QaHS5zeXNtbC5SZW5kZXJEb2N1bWVudFJlc3BvbnNlQipaKGdpdGh1Yi5jb20vT3Blbi1NQkVFL09wZW5TeXNNTC9hcGkvcHJvdG9iBnByb3RvMw"); + fileDesc("CgtzeXNtbC5wcm90bxIFc3lzbWwi4gEKB1ZlcmRpY3QSDAoEa2luZBgBIAEoCRISCgplbGVtZW50X2lkGAIgASgJEg8KB2VsZW1lbnQYAyABKAkSDQoFaG9sZHMYBCABKAgSEQoJY29uZGl0aW9uGAUgASgJEhMKC2luc3RhbmNlX2lkGAYgASgDEhgKEGluc3RhbmNlX3R5cGVfaWQYByABKAkSDQoFZXJyb3IYCCABKAkSLAoOZmFpbHVyZV9yZWFzb24YCSABKA4yFC5zeXNtbC5GYWlsdXJlUmVhc29uEhYKDnJlcXVpcmVtZW50X2lkGAogASgJIlsKF1ZlcmlmeUNvbnN0cmFpbnRSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSEQoJc3ltYm9sX2lkGAIgASgJEhkKEXN1YmplY3Rfc3ltYm9sX2lkGAMgASgJIpYBChhWZXJpZnlDb25zdHJhaW50UmVzcG9uc2USHwoHdmVyZGljdBgBIAEoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAIgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljIlwKGFZlcmlmeVJlcXVpcmVtZW50UmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCRIZChFzdWJqZWN0X3N5bWJvbF9pZBgDIAEoCSJtChNWZXJpZmljYXRpb25WZXJkaWN0Eg8KB2Nhc2VfaWQYASABKAkSDAoEa2luZBgCIAEoCRIOCgZkZXRhaWwYAyABKAkSDwoHc3ViY2FzZRgEIAEoCBIWCg5yZXF1aXJlbWVudF9pZBgFIAEoCSLSAQoZVmVyaWZ5UmVxdWlyZW1lbnRSZXNwb25zZRIfCgd2ZXJkaWN0GAEgASgLMg4uc3lzbWwuVmVyZGljdBIiCglpbnN0YW5jZXMYAiADKAsyDy5zeXNtbC5JbnN0YW5jZRINCgVlcnJvchgDIAEoCRImCgtkaWFnbm9zdGljcxgEIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSOQoVdmVyaWZpY2F0aW9uX3ZlcmRpY3RzGAUgAygLMhouc3lzbWwuVmVyaWZpY2F0aW9uVmVyZGljdCJCChlWZXJpZnlTYXRpc2ZhY3Rpb25SZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSEQoJc3ltYm9sX2lkGAIgASgJIoICChpWZXJpZnlTYXRpc2ZhY3Rpb25SZXNwb25zZRIgCgh2ZXJkaWN0cxgBIAMoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAIgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljEiwKDmZhaWx1cmVfcmVhc29uGAUgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbhI5ChV2ZXJpZmljYXRpb25fdmVyZGljdHMYBiADKAsyGi5zeXNtbC5WZXJpZmljYXRpb25WZXJkaWN0Il0KE0V2YWx1YXRlQ2FsY1JlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIRCglzeW1ib2xfaWQYAiABKAkSHwoJYXJndW1lbnRzGAMgAygLMgwuc3lzbWwuVmFsdWUivQEKFEV2YWx1YXRlQ2FsY1Jlc3BvbnNlEhwKBnJlc3VsdBgBIAEoCzIMLnN5c21sLlZhbHVlEiIKB291dHB1dHMYAiADKAsyES5zeXNtbC5DYWxjT3V0cHV0Eg0KBWVycm9yGAMgASgJEiYKC2RpYWdub3N0aWNzGAQgAygLMhEuc3lzbWwuRGlhZ25vc3RpYxIsCg5mYWlsdXJlX3JlYXNvbhgFIAEoDjIULnN5c21sLkZhaWx1cmVSZWFzb24iNwoKQ2FsY091dHB1dBIMCgRuYW1lGAEgASgJEhsKBXZhbHVlGAIgASgLMgwuc3lzbWwuVmFsdWUihAIKElJ1bkFuYWx5c2lzUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCRIZChFzdWJqZWN0X3N5bWJvbF9pZBgDIAEoCRIfCglhcmd1bWVudHMYBCADKAsyDC5zeXNtbC5WYWx1ZRJGCg9uYW1lZF9hcmd1bWVudHMYBSADKAsyLS5zeXNtbC5SdW5BbmFseXNpc1JlcXVlc3QuTmFtZWRBcmd1bWVudHNFbnRyeRpDChNOYW1lZEFyZ3VtZW50c0VudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASKfAgoTUnVuQW5hbHlzaXNSZXNwb25zZRIiCgdvdXRwdXRzGAEgAygLMhEuc3lzbWwuQ2FsY091dHB1dBIgCgh2ZXJkaWN0cxgCIAMoCzIOLnN5c21sLlZlcmRpY3QSIgoJaW5zdGFuY2VzGAMgAygLMg8uc3lzbWwuSW5zdGFuY2USDQoFZXJyb3IYBCABKAkSJgoLZGlhZ25vc3RpY3MYBSADKAsyES5zeXNtbC5EaWFnbm9zdGljEiwKDmZhaWx1cmVfcmVhc29uGAYgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbhI5ChV2ZXJpZmljYXRpb25fdmVyZGljdHMYByADKAsyGi5zeXNtbC5WZXJpZmljYXRpb25WZXJkaWN0IowBChBQYXJzZUZpbGVSZXF1ZXN0EhMKCWZpbGVfcGF0aBgBIAEoCUgAEhEKB2NvbnRlbnQYAiABKAlIABIYCgxjb250ZW50X2hhc2gYAyABKAlCAhgBEhAKCGxhbmd1YWdlGAQgASgJEhoKEnN0cmljdF9jb25mb3JtYW5jZRgFIAEoCEIICgZzb3VyY2UiYgoOU291cmNlRG9jdW1lbnQSEwoJZmlsZV9wYXRoGAEgASgJSAASEQoHY29udGVudBgCIAEoCUgAEhAKCGxhbmd1YWdlGAMgASgJEgwKBG5hbWUYBCABKAlCCAoGc291cmNlIlsKE1BhcnNlU291cmNlc1JlcXVlc3QSKAoJZG9jdW1lbnRzGAEgAygLMhUuc3lzbWwuU291cmNlRG9jdW1lbnQSGgoSc3RyaWN0X2NvbmZvcm1hbmNlGAIgASgIIoMBChRQYXJzZVNvdXJjZXNSZXNwb25zZRISCgptb2RlbF9oYXNoGAEgASgJEiAKBXJvb3RzGAIgAygLMhEuc3lzbWwuU3ltYm9sSW5mbxImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSDQoFZXJyb3IYBCABKAkifwoRUGFyc2VGaWxlUmVzcG9uc2USEgoKbW9kZWxfaGFzaBgBIAEoCRIfCgRyb290GAIgASgLMhEuc3lzbWwuU3ltYm9sSW5mbxImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSDQoFZXJyb3IYBCABKAkiOQoQR2V0U3ltYm9sUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhEKCXN5bWJvbF9pZBgCIAEoCSJCCg5TeW1ib2xSZXNwb25zZRIhCgZzeW1ib2wYASABKAsyES5zeXNtbC5TeW1ib2xJbmZvEg0KBWVycm9yGAIgASgJIigKEkRpYWdub3N0aWNzUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJIkwKE0RpYWdub3N0aWNzUmVzcG9uc2USJgoLZGlhZ25vc3RpY3MYASADKAsyES5zeXNtbC5EaWFnbm9zdGljEg0KBWVycm9yGAIgASgJIm8KD0V2YWx1YXRlUmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhIKCmV4cHJlc3Npb24YAiABKAkSGQoRY29udGV4dF9zeW1ib2xfaWQYAyABKAkSGQoRc3ViamVjdF9zeW1ib2xfaWQYBCABKAkiZwoQRXZhbHVhdGVSZXNwb25zZRIcCgZyZXN1bHQYASABKAsyDC5zeXNtbC5WYWx1ZRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMiwgEKCEluc3RhbmNlEgoKAmlkGAEgASgDEhYKDnR5cGVfc3ltYm9sX2lkGAIgASgJEjoKDmZlYXR1cmVfdmFsdWVzGAQgAygLMiIuc3lzbWwuSW5zdGFuY2UuRmVhdHVyZVZhbHVlc0VudHJ5GkkKEkZlYXR1cmVWYWx1ZXNFbnRyeRILCgNrZXkYASABKAkSIgoFdmFsdWUYAiABKAsyEy5zeXNtbC5GZWF0dXJlVmFsdWU6AjgBSgQIAxAEUgVzbG90cyKEAQoMRmVhdHVyZVZhbHVlEhQKDGZlYXR1cmVfbmFtZRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlEhwKBnZhbHVlcxgDIAMoCzIMLnN5c21sLlZhbHVlEhQKDG1hdGVyaWFsaXplZBgEIAEoCBINCgVlcnJvchgFIAEoCSI7ChJJbnN0YW50aWF0ZVJlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIRCglzeW1ib2xfaWQYAiABKAkikwEKE0luc3RhbnRpYXRlUmVzcG9uc2USIQoIaW5zdGFuY2UYASABKAsyDy5zeXNtbC5JbnN0YW5jZRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSIgoJaW5zdGFuY2VzGAQgAygLMg8uc3lzbWwuSW5zdGFuY2UiugEKFEV4ZWN1dGVBY3Rpb25SZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSGAoQYWN0aW9uX3N5bWJvbF9pZBgCIAEoCRI3CgZpbnB1dHMYAyADKAsyJy5zeXNtbC5FeGVjdXRlQWN0aW9uUmVxdWVzdC5JbnB1dHNFbnRyeRo7CgtJbnB1dHNFbnRyeRILCgNrZXkYASABKAkSGwoFdmFsdWUYAiABKAsyDC5zeXNtbC5WYWx1ZToCOAEiyAEKFUV4ZWN1dGVBY3Rpb25SZXNwb25zZRI6CgdvdXRwdXRzGAEgAygLMikuc3lzbWwuRXhlY3V0ZUFjdGlvblJlc3BvbnNlLk91dHB1dHNFbnRyeRINCgVlcnJvchgCIAEoCRImCgtkaWFnbm9zdGljcxgDIAMoCzIRLnN5c21sLkRpYWdub3N0aWMaPAoMT3V0cHV0c0VudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASJaChNFeGVjdXRlU3RhdGVSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSHwoXc3RhdGVfbWFjaGluZV9zeW1ib2xfaWQYAiABKAkSDgoGZXZlbnRzGAMgAygJIu4BChRFeGVjdXRlU3RhdGVSZXNwb25zZRIWCg5zdGF0ZXNfdmlzaXRlZBgBIAMoCRJECg1maW5hbF9jb250ZXh0GAIgAygLMi0uc3lzbWwuRXhlY3V0ZVN0YXRlUmVzcG9uc2UuRmluYWxDb250ZXh0RW50cnkSDQoFZXJyb3IYAyABKAkSJgoLZGlhZ25vc3RpY3MYBCADKAsyES5zeXNtbC5EaWFnbm9zdGljGkEKEUZpbmFsQ29udGV4dEVudHJ5EgsKA2tleRgBIAEoCRIbCgV2YWx1ZRgCIAEoCzIMLnN5c21sLlZhbHVlOgI4ASKgAQoOQ29udmVydFJlcXVlc3QSEwoJZmlsZV9wYXRoGAEgASgJSAASEQoHY29udGVudBgCIAEoCUgAEhQKCm1vZGVsX2hhc2gYBiABKAlIABITCgtmcm9tX2Zvcm1hdBgDIAEoCRIRCgl0b19mb3JtYXQYBCABKAkSHgoWdG9sZXJhdGVfc3ludGF4X2Vycm9ycxgFIAEoCEIICgZzb3VyY2UitAEKD0NvbnZlcnRSZXNwb25zZRIPCgdjb250ZW50GAEgASgJEhMKC2Zyb21fZm9ybWF0GAIgASgJEhEKCXRvX2Zvcm1hdBgDIAEoCRINCgVlcnJvchgEIAEoCRImCgtkaWFnbm9zdGljcxgFIAMoCzIRLnN5c21sLkRpYWdub3N0aWMSFAoMZXhwZXJpbWVudGFsGAYgASgIEhsKE2V4cGVyaW1lbnRhbF9ub3RpY2UYByABKAkiUQoRQXBwbHlFZGl0c1JlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIoCgpvcGVyYXRpb25zGAIgAygLMhQuc3lzbWwuRWRpdE9wZXJhdGlvbiK8AQoNRWRpdE9wZXJhdGlvbhIoCglzZXRfdmFsdWUYASABKAsyEy5zeXNtbC5TZXRWYWx1ZUVkaXRIABIjCgZyZW5hbWUYAiABKAsyES5zeXNtbC5SZW5hbWVFZGl0SAASKgoKYWRkX21lbWJlchgDIAEoCzIULnN5c21sLkFkZE1lbWJlckVkaXRIABIjCgZkZWxldGUYBCABKAsyES5zeXNtbC5EZWxldGVFZGl0SABCCwoJb3BlcmF0aW9uIoIBCg1BZGRNZW1iZXJFZGl0Eg0KBW93bmVyGAEgASgJEgwKBGtpbmQYAiABKAkSDAoEbmFtZRgDIAEoCRIMCgR0eXBlGAQgASgJEhQKDG11bHRpcGxpY2l0eRgFIAEoCRINCgV2YWx1ZRgGIAEoCRITCgtzcGVjaWFsaXplcxgHIAMoCSItCgpEZWxldGVFZGl0Eg4KBnRhcmdldBgBIAEoCRIPCgdjYXNjYWRlGAIgASgIIi0KDFNldFZhbHVlRWRpdBIOCgZ0YXJnZXQYASABKAkSDQoFdmFsdWUYAiABKAkiLgoKUmVuYW1lRWRpdBIOCgZ0YXJnZXQYASABKAkSEAoIbmV3X25hbWUYAiABKAkiwgEKEkFwcGx5RWRpdHNSZXNwb25zZRIPCgdjb250ZW50GAEgASgJEiMKB2FwcGxpZWQYAiADKAsyEi5zeXNtbC5BcHBsaWVkRWRpdBINCgVlcnJvchgDIAEoCRIjCgdmYWlsdXJlGAQgASgOMhIuc3lzbWwuRWRpdEZhaWx1cmUSJgoLZGlhZ25vc3RpY3MYBSADKAsyES5zeXNtbC5EaWFnbm9zdGljEhoKEnJlZmVycmluZ19lbGVtZW50cxgGIAMoCSJ6CgtBcHBsaWVkRWRpdBIXCg9vcGVyYXRpb25faW5kZXgYASABKAUSDgoGdGFyZ2V0GAIgASgJEg4KBm9mZnNldBgDIAEoBRIOCgZsZW5ndGgYBCABKAUSEAoIb2xkX3RleHQYBSABKAkSEAoIbmV3X3RleHQYBiABKAki/QIKClN5bWJvbEluZm8SCgoCaWQYASABKAkSDAoEbmFtZRgCIAEoCRIMCgRraW5kGAMgASgJEjEKCG1ldGFkYXRhGAQgAygLMh8uc3lzbWwuU3ltYm9sSW5mby5NZXRhZGF0YUVudHJ5EhEKCWNoaWxkX2lkcxgFIAMoCRIoCgphdHRyaWJ1dGVzGAYgAygLMhQuc3lzbWwuQXR0cmlidXRlSW5mbxIiCgl0eXBlX2luZm8YByABKAsyDy5zeXNtbC5UeXBlSW5mbxItCgxtdWx0aXBsaWNpdHkYCCABKAsyFy5zeXNtbC5NdWx0aXBsaWNpdHlJbmZvEi4KD3NwZWNpYWxpemF0aW9ucxgJIAMoCzIVLnN5c21sLlNwZWNpYWxpemF0aW9uEiMKG3dpdGhoZWxkX2xpYnJhcnlfYXR0cmlidXRlcxgKIAEoBRovCg1NZXRhZGF0YUVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEiWAoOU3BlY2lhbGl6YXRpb24SDAoEa2luZBgBIAEoCRIQCghkZWNsYXJlZBgCIAEoCRIRCgl0YXJnZXRfaWQYAyABKAkSEwoLdGFyZ2V0X2tpbmQYBCABKAkilQEKCFR5cGVJbmZvEhAKCGRlY2xhcmVkGAEgASgJEhMKC3Jlc29sdmVkX2lkGAIgASgJEhUKDXJlc29sdmVkX2tpbmQYAyABKAkSEQoJcHJpbWl0aXZlGAQgASgJEhgKEHByaW1pdGl2ZV9zb3VyY2UYBSABKAkSEAoIcXVhbnRpdHkYBiABKAgSDAoEdW5pdBgHIAEoCSIwChBNdWx0aXBsaWNpdHlJbmZvEg0KBWxvd2VyGAEgASgJEg0KBXVwcGVyGAIgASgJIlYKDUF0dHJpYnV0ZUluZm8SDAoEbmFtZRgBIAEoCRIMCgR0eXBlGAIgASgJEhsKBXZhbHVlGAMgASgLMgwuc3lzbWwuVmFsdWUSDAoEdW5pdBgEIAEoCSKbBAoFVmFsdWUSEwoJaW50X3ZhbHVlGAEgASgDSAASFAoKcmVhbF92YWx1ZRgCIAEoAUgAEhQKCmJvb2xfdmFsdWUYAyABKAhIABIWCgxzdHJpbmdfdmFsdWUYBCABKAlIABIVCgtpbnN0YW5jZV9pZBgFIAEoA0gAEigKCHNlcXVlbmNlGAYgASgLMhQuc3lzbWwuVmFsdWVTZXF1ZW5jZUgAEg4KBG51bGwYByABKAlIABIjCghxdWFudGl0eRgIIAEoCzIPLnN5c21sLlF1YW50aXR5SAASKgoMZW51bV9saXRlcmFsGAkgASgLMhIuc3lzbWwuRW51bUxpdGVyYWxIABIPCgV1bnNldBgKIAEoCEgAEiEKB2NvbXBsZXgYCyABKAsyDi5zeXNtbC5Db21wbGV4SAASHQoFYXJyYXkYDCABKAsyDC5zeXNtbC5BcnJheUgAEh8KBnZlY3RvchgNIAEoCzINLnN5c21sLlZlY3RvckgAEjAKD3ZlY3Rvcl9xdWFudGl0eRgOIAEoCzIVLnN5c21sLlZlY3RvclF1YW50aXR5SAASMAoPbWVhc3VyZW1lbnRfcmVmGA8gASgLMhUuc3lzbWwuTWVhc3VyZW1lbnRSZWZIABISCghpbmZpbml0eRgQIAEoCEgAEiMKCGZ1bmN0aW9uGBEgASgLMg8uc3lzbWwuRnVuY3Rpb25IAEIGCgRraW5kIiwKCEZ1bmN0aW9uEg8KB2NhbGNfaWQYASABKAkSDwoHc2VsZl9pZBgCIAEoAyI7CgVBcnJheRISCgpkaW1lbnNpb25zGAEgAygDEh4KCGVsZW1lbnRzGAIgAygLMgwuc3lzbWwuVmFsdWUiKgoGVmVjdG9yEiAKCmNvbXBvbmVudHMYASADKAsyDC5zeXNtbC5WYWx1ZSI1Cg5WZWN0b3JRdWFudGl0eRIjCgpjb21wb25lbnRzGAEgAygLMg8uc3lzbWwuUXVhbnRpdHkiKgoHQ29tcGxleBIMCgRyZWFsGAEgASgBEhEKCWltYWdpbmFyeRgCIAEoASJHCgtFbnVtTGl0ZXJhbBISCgpsaXRlcmFsX2lkGAEgASgJEhYKDmVudW1lcmF0aW9uX2lkGAIgASgJEgwKBG5hbWUYAyABKAkiLwoNVmFsdWVTZXF1ZW5jZRIeCghlbGVtZW50cxgBIAMoCzIMLnN5c21sLlZhbHVlInwKCFF1YW50aXR5EhcKDWludF9tYWduaXR1ZGUYASABKANIABIYCg5yZWFsX21hZ25pdHVkZRgCIAEoAUgAEgwKBHVuaXQYAyABKAkSIgoJdW5pdF90ZXJtGAQgASgLMg8uc3lzbWwuVW5pdFRlcm1CCwoJbWFnbml0dWRlIlMKDk1lYXN1cmVtZW50UmVmEgwKBHVuaXQYASABKAkSIgoJdW5pdF90ZXJtGAIgASgLMg8uc3lzbWwuVW5pdFRlcm0SDwoHdW5pdF9pZBgDIAEoCSJUCghVbml0VGVybRIRCglzY2FsZV9udW0YASABKAESEQoJc2NhbGVfZGVuGAIgASgBEiIKB2ZhY3RvcnMYAyADKAsyES5zeXNtbC5Vbml0RmFjdG9yIi8KClVuaXRGYWN0b3ISDwoHdW5pdF9pZBgBIAEoCRIQCghleHBvbmVudBgCIAEoASJYCgpEaWFnbm9zdGljEhAKCHNldmVyaXR5GAEgASgJEg8KB21lc3NhZ2UYAiABKAkSGQoEc3BhbhgDIAEoCzILLnN5c21sLlNwYW4SDAoEY29kZRgEIAEoCSJeCgRTcGFuEgwKBGZpbGUYASABKAkSEgoKc3RhcnRfbGluZRgCIAEoBRIRCglzdGFydF9jb2wYAyABKAUSEAoIZW5kX2xpbmUYBCABKAUSDwoHZW5kX2NvbBgFIAEoBSITChFTZXJ2ZXJJbmZvUmVxdWVzdCI7ChJTZXJ2ZXJJbmZvUmVzcG9uc2USDwoHdmVyc2lvbhgBIAEoCRIUCgxjYXBhYmlsaXRpZXMYAiADKAkiUwoMUXVlcnlSZXF1ZXN0EhIKCm1vZGVsX2hhc2gYASABKAkSGwoFcXVlcnkYAiABKAsyDC5zeXNtbC5RdWVyeRISCgpvc2xjX3F1ZXJ5GAMgASgJIjwKDVF1ZXJ5UmVzcG9uc2USKwoIZWxlbWVudHMYASADKAsyGS5zeXNtbC5RdWVyeVJlc3VsdEVsZW1lbnQiSAoFUXVlcnkSDQoFc2NvcGUYASADKAkSDgoGc2VsZWN0GAIgAygJEiAKBXdoZXJlGAMgASgLMhEuc3lzbWwuQ29uc3RyYWludCJ8CgpDb25zdHJhaW50Ei8KCXByaW1pdGl2ZRgBIAEoCzIaLnN5c21sLlByaW1pdGl2ZUNvbnN0cmFpbnRIABIvCgljb21wb3NpdGUYAiABKAsyGi5zeXNtbC5Db21wb3NpdGVDb25zdHJhaW50SABCDAoKY29uc3RyYWludCJzChNQcmltaXRpdmVDb25zdHJhaW50Eg8KB2ludmVyc2UYASABKAgSEAoIcHJvcGVydHkYAiABKAkSKgoIb3BlcmF0b3IYAyABKA4yGC5zeXNtbC5QcmltaXRpdmVPcGVyYXRvchINCgV2YWx1ZRgEIAMoCSJoChNDb21wb3NpdGVDb25zdHJhaW50EioKCG9wZXJhdG9yGAEgASgOMhguc3lzbWwuQ29tcG9zaXRlT3BlcmF0b3ISJQoKY29uc3RyYWludBgCIAMoCzIRLnN5c21sLkNvbnN0cmFpbnQioAEKElF1ZXJ5UmVzdWx0RWxlbWVudBIKCgJpZBgBIAEoCRIMCgR0eXBlGAIgASgJEj0KCnByb3BlcnRpZXMYAyADKAsyKS5zeXNtbC5RdWVyeVJlc3VsdEVsZW1lbnQuUHJvcGVydGllc0VudHJ5GjEKD1Byb3BlcnRpZXNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBInMKClN3ZWVwUmFuZ2USEQoJcGFyYW1ldGVyGAEgASgJEhsKBXN0YXJ0GAIgASgLMgwuc3lzbWwuVmFsdWUSGQoDZW5kGAMgASgLMgwuc3lzbWwuVmFsdWUSGgoEc3RlcBgEIAEoCzIMLnN5c21sLlZhbHVlIsACCg9SdW5Td2VlcFJlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRIRCglzeW1ib2xfaWQYAiABKAkSGQoRc3ViamVjdF9zeW1ib2xfaWQYAyABKAkSHwoJYXJndW1lbnRzGAQgAygLMgwuc3lzbWwuVmFsdWUSQwoPbmFtZWRfYXJndW1lbnRzGAUgAygLMiouc3lzbWwuUnVuU3dlZXBSZXF1ZXN0Lk5hbWVkQXJndW1lbnRzRW50cnkSIQoGcmFuZ2VzGAYgAygLMhEuc3lzbWwuU3dlZXBSYW5nZRIPCgdzYW1wbGVzGAcgASgDEgwKBHNlZWQYCCABKAQaQwoTTmFtZWRBcmd1bWVudHNFbnRyeRILCgNrZXkYASABKAkSGwoFdmFsdWUYAiABKAsyDC5zeXNtbC5WYWx1ZToCOAEiyAEKCFN3ZWVwUm93EiEKBmlucHV0cxgBIAMoCzIRLnN5c21sLkNhbGNPdXRwdXQSIgoHb3V0cHV0cxgCIAMoCzIRLnN5c21sLkNhbGNPdXRwdXQSIAoIdmVyZGljdHMYAyADKAsyDi5zeXNtbC5WZXJkaWN0EhYKDmVsYXBzZWRfbWljcm9zGAQgASgDEg0KBWVycm9yGAUgASgJEiwKDmZhaWx1cmVfcmVhc29uGAYgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbiLtAQoQUnVuU3dlZXBSZXNwb25zZRIdCgRyb3dzGAEgAygLMg8uc3lzbWwuU3dlZXBSb3cSEgoKcGFyYW1ldGVycxgCIAMoCRIPCgdzYW1wbGVkGAMgASgIEgwKBHNlZWQYBCABKAQSDQoFZXJyb3IYBSABKAkSJgoLZGlhZ25vc3RpY3MYBiADKAsyES5zeXNtbC5EaWFnbm9zdGljEiwKDmZhaWx1cmVfcmVhc29uGAcgASgOMhQuc3lzbWwuRmFpbHVyZVJlYXNvbhIiCglpbnN0YW5jZXMYCCADKAsyDy5zeXNtbC5JbnN0YW5jZSJuChdSdW5Eb2N1bWVudFF1ZXJ5UmVxdWVzdBISCgptb2RlbF9oYXNoGAEgASgJEhAKCHF1ZXJ5X2lkGAIgASgJEi0KCGJpbmRpbmdzGAMgAygLMhsuc3lzbWwuRG9jdW1lbnRRdWVyeUJpbmRpbmciTwoURG9jdW1lbnRRdWVyeUJpbmRpbmcSEQoJcGFyYW1ldGVyGAEgASgJEiQKBnZhbHVlcxgCIAMoCzIULnN5c21sLkRvY3VtZW50VmFsdWUi1QEKDURvY3VtZW50VmFsdWUSFAoKZWxlbWVudF9pZBgBIAEoCUgAEhYKDHN0cmluZ192YWx1ZRgCIAEoCUgAEhMKCWludF92YWx1ZRgDIAEoA0gAEhQKCnJlYWxfdmFsdWUYBCABKAFIABIUCgpib29sX3ZhbHVlGAUgASgISAASEgoIaW5maW5pdHkYBiABKAhIABIjCghxdWFudGl0eRgIIAEoCzIPLnN5c21sLlF1YW50aXR5SAASFAoMZWxlbWVudF90eXBlGAcgASgJQgYKBGtpbmQiIwoTRG9jdW1lbnRRdWVyeUNvbHVtbhIMCgRuYW1lGAEgASgJIjkKEURvY3VtZW50UXVlcnlDZWxsEiQKBnZhbHVlcxgBIAMoCzIULnN5c21sLkRvY3VtZW50VmFsdWUiYgoQRG9jdW1lbnRRdWVyeVJvdxIlCgdlbGVtZW50GAEgASgLMhQuc3lzbWwuRG9jdW1lbnRWYWx1ZRInCgVjZWxscxgCIAMoCzIYLnN5c21sLkRvY3VtZW50UXVlcnlDZWxsIm4KGFJ1bkRvY3VtZW50UXVlcnlSZXNwb25zZRIrCgdjb2x1bW5zGAEgAygLMhouc3lzbWwuRG9jdW1lbnRRdWVyeUNvbHVtbhIlCgRyb3dzGAIgAygLMhcuc3lzbWwuRG9jdW1lbnRRdWVyeVJvdyJAChVSZW5kZXJEb2N1bWVudFJlcXVlc3QSEgoKbW9kZWxfaGFzaBgBIAEoCRITCgtkb2N1bWVudF9pZBgCIAEoCSIqChZSZW5kZXJEb2N1bWVudFJlc3BvbnNlEhAKCG1hcmtkb3duGAEgASgJKpMBCg1GYWlsdXJlUmVhc29uEh4KGkZBSUxVUkVfUkVBU09OX1VOU1BFQ0lGSUVEEAASHQoZRkFJTFVSRV9SRUFTT05fRVZBTFVBVElPThABEh0KGUZBSUxVUkVfUkVBU09OX1dST05HX0tJTkQQAhIkCiBGQUlMVVJFX1JFQVNPTl9BTUJJR1VPVVNfU1VCSkVDVBADKp0ECgtFZGl0RmFpbHVyZRIcChhFRElUX0ZBSUxVUkVfVU5TUEVDSUZJRUQQABIeChpFRElUX0ZBSUxVUkVfTk9fT1BFUkFUSU9OUxABEh8KG0VESVRfRkFJTFVSRV9VTktOT1dOX1RBUkdFVBACEiEKHUVESVRfRkFJTFVSRV9BTUJJR1VPVVNfVEFSR0VUEAMSGwoXRURJVF9GQUlMVVJFX05PVF9WQUxVRUQQBBIeChpFRElUX0ZBSUxVUkVfSU5WQUxJRF9WQUxVRRAFEh0KGUVESVRfRkFJTFVSRV9JTlZBTElEX05BTUUQBhIaChZFRElUX0ZBSUxVUkVfTk9UX05BTUVEEAcSIgoeRURJVF9GQUlMVVJFX1JFTkFNRV9SRUZFUkVOQ0VEEAgSIgoeRURJVF9GQUlMVVJFX09WRVJMQVBQSU5HX0VESVRTEAkSHwobRURJVF9GQUlMVVJFX1JFU1VMVF9JTlZBTElEEAoSHgoaRURJVF9GQUlMVVJFX09XTkVSX1VOS05PV04QCxIkCiBFRElUX0ZBSUxVUkVfT1dORVJfTk9UX05BTUVTUEFDRRAMEh0KGUVESVRfRkFJTFVSRV9JTExFR0FMX0tJTkQQDRIiCh5FRElUX0ZBSUxVUkVfTUVNQkVSX05BTUVfVEFLRU4QDhIiCh5FRElUX0ZBSUxVUkVfREVMRVRFX1JFRkVSRU5DRUQQDyqSAQoRUHJpbWl0aXZlT3BlcmF0b3ISIgoeUFJJTUlUSVZFX09QRVJBVE9SX1VOU1BFQ0lGSUVEEAASHAoYUFJJTUlUSVZFX09QRVJBVE9SX0VRVUFMEAESHgoaUFJJTUlUSVZFX09QRVJBVE9SX0dSRUFURVIQAhIbChdQUklNSVRJVkVfT1BFUkFUT1JfTEVTUxADKm4KEUNvbXBvc2l0ZU9wZXJhdG9yEiIKHkNPTVBPU0lURV9PUEVSQVRPUl9VTlNQRUNJRklFRBAAEhoKFkNPTVBPU0lURV9PUEVSQVRPUl9BTkQQARIZChVDT01QT1NJVEVfT1BFUkFUT1JfT1IQAjKkCwoMU3lzTUxTZXJ2aWNlEkQKDUdldFNlcnZlckluZm8SGC5zeXNtbC5TZXJ2ZXJJbmZvUmVxdWVzdBoZLnN5c21sLlNlcnZlckluZm9SZXNwb25zZRI+CglQYXJzZUZpbGUSFy5zeXNtbC5QYXJzZUZpbGVSZXF1ZXN0Ghguc3lzbWwuUGFyc2VGaWxlUmVzcG9uc2USRwoMUGFyc2VTb3VyY2VzEhouc3lzbWwuUGFyc2VTb3VyY2VzUmVxdWVzdBobLnN5c21sLlBhcnNlU291cmNlc1Jlc3BvbnNlEjsKCUdldFN5bWJvbBIXLnN5c21sLkdldFN5bWJvbFJlcXVlc3QaFS5zeXNtbC5TeW1ib2xSZXNwb25zZRJHCg5HZXREaWFnbm9zdGljcxIZLnN5c21sLkRpYWdub3N0aWNzUmVxdWVzdBoaLnN5c21sLkRpYWdub3N0aWNzUmVzcG9uc2USOwoIRXZhbHVhdGUSFi5zeXNtbC5FdmFsdWF0ZVJlcXVlc3QaFy5zeXNtbC5FdmFsdWF0ZVJlc3BvbnNlEkQKC0luc3RhbnRpYXRlEhkuc3lzbWwuSW5zdGFudGlhdGVSZXF1ZXN0Ghouc3lzbWwuSW5zdGFudGlhdGVSZXNwb25zZRJKCg1FeGVjdXRlQWN0aW9uEhsuc3lzbWwuRXhlY3V0ZUFjdGlvblJlcXVlc3QaHC5zeXNtbC5FeGVjdXRlQWN0aW9uUmVzcG9uc2USRwoMRXhlY3V0ZVN0YXRlEhouc3lzbWwuRXhlY3V0ZVN0YXRlUmVxdWVzdBobLnN5c21sLkV4ZWN1dGVTdGF0ZVJlc3BvbnNlEjgKB0NvbnZlcnQSFS5zeXNtbC5Db252ZXJ0UmVxdWVzdBoWLnN5c21sLkNvbnZlcnRSZXNwb25zZRJBCgpBcHBseUVkaXRzEhguc3lzbWwuQXBwbHlFZGl0c1JlcXVlc3QaGS5zeXNtbC5BcHBseUVkaXRzUmVzcG9uc2USUwoQVmVyaWZ5Q29uc3RyYWludBIeLnN5c21sLlZlcmlmeUNvbnN0cmFpbnRSZXF1ZXN0Gh8uc3lzbWwuVmVyaWZ5Q29uc3RyYWludFJlc3BvbnNlElYKEVZlcmlmeVJlcXVpcmVtZW50Eh8uc3lzbWwuVmVyaWZ5UmVxdWlyZW1lbnRSZXF1ZXN0GiAuc3lzbWwuVmVyaWZ5UmVxdWlyZW1lbnRSZXNwb25zZRJZChJWZXJpZnlTYXRpc2ZhY3Rpb24SIC5zeXNtbC5WZXJpZnlTYXRpc2ZhY3Rpb25SZXF1ZXN0GiEuc3lzbWwuVmVyaWZ5U2F0aXNmYWN0aW9uUmVzcG9uc2USRwoMRXZhbHVhdGVDYWxjEhouc3lzbWwuRXZhbHVhdGVDYWxjUmVxdWVzdBobLnN5c21sLkV2YWx1YXRlQ2FsY1Jlc3BvbnNlEkQKC1J1bkFuYWx5c2lzEhkuc3lzbWwuUnVuQW5hbHlzaXNSZXF1ZXN0Ghouc3lzbWwuUnVuQW5hbHlzaXNSZXNwb25zZRI7CghSdW5Td2VlcBIWLnN5c21sLlJ1blN3ZWVwUmVxdWVzdBoXLnN5c21sLlJ1blN3ZWVwUmVzcG9uc2USMgoFUXVlcnkSEy5zeXNtbC5RdWVyeVJlcXVlc3QaFC5zeXNtbC5RdWVyeVJlc3BvbnNlElMKEFJ1bkRvY3VtZW50UXVlcnkSHi5zeXNtbC5SdW5Eb2N1bWVudFF1ZXJ5UmVxdWVzdBofLnN5c21sLlJ1bkRvY3VtZW50UXVlcnlSZXNwb25zZRJNCg5SZW5kZXJEb2N1bWVudBIcLnN5c21sLlJlbmRlckRvY3VtZW50UmVxdWVzdBodLnN5c21sLlJlbmRlckRvY3VtZW50UmVzcG9uc2VCKlooZ2l0aHViLmNvbS9PcGVuLU1CRUUvT3BlblN5c01ML2FwaS9wcm90b2IGcHJvdG8z"); /** * Verdict is one verification's answer: whether the condition held, and, when @@ -2520,6 +2520,14 @@ export type Diagnostic = Message<"sysml.Diagnostic"> & { * @generated from field: sysml.Span span = 3; */ span?: Span | undefined; + + /** + * Stable identifier to branch on instead of the message: a pass or rule code, + * "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned. + * + * @generated from field: string code = 4; + */ + code: string; }; /** @@ -2654,6 +2662,8 @@ export type ServerInfoResponse = Message<"sysml.ServerInfoResponse"> & { * and answers with typed rows. * "render_document" - the RenderDocument RPC renders a named document to * Markdown. + * "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + * finding none was assigned; without it every code is empty. * * @generated from field: repeated string capabilities = 2; */ diff --git a/clients/node/test/client.test.ts b/clients/node/test/client.test.ts index 4e5b0970d..91569a67e 100644 --- a/clients/node/test/client.test.ts +++ b/clients/node/test/client.test.ts @@ -9,6 +9,7 @@ import { join } from "node:path"; import { after, before, test } from "node:test"; import { CAPABILITY_COMPLEX_VALUES, + CAPABILITY_DIAGNOSTIC_CODES, CAPABILITY_FUNCTION_VALUES, CAPABILITY_MEASUREMENT_REFS, CAPABILITY_QUERY, @@ -269,6 +270,18 @@ test("a file parses, and a syntax error is a diagnostic, not a thrown call", asy assert.ok(broken.diagnostics.some((diagnostic) => diagnostic.severity === "error")); }); +test("a diagnostic carries the service's code for what it found", async () => { + await using connection = await connect(); + assert.ok((await connection.serverInfo()).has(CAPABILITY_DIAGNOSTIC_CODES)); + const broken = await connection.loads("package Broken { part def }"); + assert.ok(broken.diagnostics.length > 0); + assert.ok(broken.diagnostics.every((diagnostic) => diagnostic.code === "syntax")); + + const unresolved = await connection.loads("package P { part def W { part hub : Missing; } }"); + assert.ok(unresolved.diagnostics.some((diagnostic) => diagnostic.code === "unresolved")); + assert.ok(unresolved.diagnostics.every((diagnostic) => diagnostic.code !== "")); +}); + test("an evaluation that cannot be made is an error the caller can catch", async () => { await using model = await loads(SAMPLE); await assert.rejects(() => model.eval("1 +"), EvaluationError); diff --git a/clients/python/README.md b/clients/python/README.md index 3ce024224..78f617401 100644 --- a/clients/python/README.md +++ b/clients/python/README.md @@ -238,6 +238,20 @@ connector usages — `action`, `state`, `calc`, `constraint`, `requirement`, so a generated class has no member for them; reach them through `model["Demo::Vehicle"]`, `verify_constraint` and `verify_satisfaction`. +## Diagnostics + +A `Diagnostic` has `severity`, `message`, `code` and a location (`file`, +`start_line`, `start_column`, `end_line`, `end_column`, or the raw `span`). Branch +on `code`, not on the message text: `"syntax"` for a syntax error, a validation +code such as `"unresolved"` for a finding, `"choice-point"` and +`"guard-unevaluable"` for a run's notes; `""` when the service assigned none. A service +that populates `code` advertises `CAPABILITY_DIAGNOSTIC_CODES`; without it every code is `""`. + +```python +model = opensysml.load("model.sysml") +unresolved = [d for d in model.diagnostics if d.code == "unresolved"] +``` + ## Names that shadow builtins Neither builtin name is a live part of the API any more: the module-level diff --git a/clients/python/opensysml/capabilities.py b/clients/python/opensysml/capabilities.py index 2948d179f..09882a0be 100644 --- a/clients/python/opensysml/capabilities.py +++ b/clients/python/opensysml/capabilities.py @@ -120,6 +120,10 @@ #: with ``UNIMPLEMENTED``. CAPABILITY_INFINITY_VALUE = "infinity_value" +#: ``Diagnostic.code`` populated, read as :attr:`~opensysml.diagnostic.Diagnostic.code`, +#: so an empty code is a finding none was assigned. Without it every code is empty. +CAPABILITY_DIAGNOSTIC_CODES = "diagnostic_codes" + @dataclass(frozen=True) class ServerInfo: diff --git a/clients/python/opensysml/diagnostic.py b/clients/python/opensysml/diagnostic.py index fbdd5356b..c95b1b393 100644 --- a/clients/python/opensysml/diagnostic.py +++ b/clients/python/opensysml/diagnostic.py @@ -7,6 +7,8 @@ class Diagnostic: Attributes: severity (str): Diagnostic severity (e.g., "error", "warning") message (str): Diagnostic message + code (str): Stable identifier of what was found (a validation code, + "syntax", "choice-point", "guard-unevaluable"); "" when none file (str): Source file name start_line (int): Starting line number (1-based) start_column (int): Starting column number (1-based) @@ -33,6 +35,11 @@ def message(self): """Get diagnostic message.""" return self._pb.message + @property + def code(self): + """Get the diagnostic code, independent of the message wording.""" + return self._pb.code + @property def span(self): """Get protobuf Span object.""" @@ -75,6 +82,7 @@ def __repr__(self): return ( f"Diagnostic(severity={self.severity!r}, " f"message={self.message!r}, " + f"code={self.code!r}, " f"file={self.file!r}, " f"line={self.start_line})" ) diff --git a/clients/python/opensysml/proto/sysml_pb2.py b/clients/python/opensysml/proto/sysml_pb2.py index 4b0e92de3..7e4499f1e 100644 --- a/clients/python/opensysml/proto/sysml_pb2.py +++ b/clients/python/opensysml/proto/sysml_pb2.py @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bsysml.proto\x12\x05sysml\"\xe2\x01\n\x07Verdict\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x12\n\nelement_id\x18\x02 \x01(\t\x12\x0f\n\x07\x65lement\x18\x03 \x01(\t\x12\r\n\x05holds\x18\x04 \x01(\x08\x12\x11\n\tcondition\x18\x05 \x01(\t\x12\x13\n\x0binstance_id\x18\x06 \x01(\x03\x12\x18\n\x10instance_type_id\x18\x07 \x01(\t\x12\r\n\x05\x65rror\x18\x08 \x01(\t\x12,\n\x0e\x66\x61ilure_reason\x18\t \x01(\x0e\x32\x14.sysml.FailureReason\x12\x16\n\x0erequirement_id\x18\n \x01(\t\"[\n\x17VerifyConstraintRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\"\x96\x01\n\x18VerifyConstraintResponse\x12\x1f\n\x07verdict\x18\x01 \x01(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\"\\\n\x18VerifyRequirementRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\"m\n\x13VerificationVerdict\x12\x0f\n\x07\x63\x61se_id\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x0e\n\x06\x64\x65tail\x18\x03 \x01(\t\x12\x0f\n\x07subcase\x18\x04 \x01(\x08\x12\x16\n\x0erequirement_id\x18\x05 \x01(\t\"\xd2\x01\n\x19VerifyRequirementResponse\x12\x1f\n\x07verdict\x18\x01 \x01(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x39\n\x15verification_verdicts\x18\x05 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"B\n\x19VerifySatisfactionRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"\x82\x02\n\x1aVerifySatisfactionResponse\x12 \n\x08verdicts\x18\x01 \x03(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x05 \x01(\x0e\x32\x14.sysml.FailureReason\x12\x39\n\x15verification_verdicts\x18\x06 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"]\n\x13\x45valuateCalcRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x1f\n\targuments\x18\x03 \x03(\x0b\x32\x0c.sysml.Value\"\xbd\x01\n\x14\x45valuateCalcResponse\x12\x1c\n\x06result\x18\x01 \x01(\x0b\x32\x0c.sysml.Value\x12\"\n\x07outputs\x18\x02 \x03(\x0b\x32\x11.sysml.CalcOutput\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x05 \x01(\x0e\x32\x14.sysml.FailureReason\"7\n\nCalcOutput\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\"\x84\x02\n\x12RunAnalysisRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\x12\x1f\n\targuments\x18\x04 \x03(\x0b\x32\x0c.sysml.Value\x12\x46\n\x0fnamed_arguments\x18\x05 \x03(\x0b\x32-.sysml.RunAnalysisRequest.NamedArgumentsEntry\x1a\x43\n\x13NamedArgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\x9f\x02\n\x13RunAnalysisResponse\x12\"\n\x07outputs\x18\x01 \x03(\x0b\x32\x11.sysml.CalcOutput\x12 \n\x08verdicts\x18\x02 \x03(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x03 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x04 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x06 \x01(\x0e\x32\x14.sysml.FailureReason\x12\x39\n\x15verification_verdicts\x18\x07 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"\x8c\x01\n\x10ParseFileRequest\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x18\n\x0c\x63ontent_hash\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08language\x18\x04 \x01(\t\x12\x1a\n\x12strict_conformance\x18\x05 \x01(\x08\x42\x08\n\x06source\"b\n\x0eSourceDocument\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x10\n\x08language\x18\x03 \x01(\t\x12\x0c\n\x04name\x18\x04 \x01(\tB\x08\n\x06source\"[\n\x13ParseSourcesRequest\x12(\n\tdocuments\x18\x01 \x03(\x0b\x32\x15.sysml.SourceDocument\x12\x1a\n\x12strict_conformance\x18\x02 \x01(\x08\"\x83\x01\n\x14ParseSourcesResponse\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12 \n\x05roots\x18\x02 \x03(\x0b\x32\x11.sysml.SymbolInfo\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"\x7f\n\x11ParseFileResponse\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1f\n\x04root\x18\x02 \x01(\x0b\x32\x11.sysml.SymbolInfo\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"9\n\x10GetSymbolRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"B\n\x0eSymbolResponse\x12!\n\x06symbol\x18\x01 \x01(\x0b\x32\x11.sysml.SymbolInfo\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"(\n\x12\x44iagnosticsRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\"L\n\x13\x44iagnosticsResponse\x12&\n\x0b\x64iagnostics\x18\x01 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"o\n\x0f\x45valuateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x12\n\nexpression\x18\x02 \x01(\t\x12\x19\n\x11\x63ontext_symbol_id\x18\x03 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x04 \x01(\t\"g\n\x10\x45valuateResponse\x12\x1c\n\x06result\x18\x01 \x01(\x0b\x32\x0c.sysml.Value\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\"\xc2\x01\n\x08Instance\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x16\n\x0etype_symbol_id\x18\x02 \x01(\t\x12:\n\x0e\x66\x65\x61ture_values\x18\x04 \x03(\x0b\x32\".sysml.Instance.FeatureValuesEntry\x1aI\n\x12\x46\x65\x61tureValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.sysml.FeatureValue:\x02\x38\x01J\x04\x08\x03\x10\x04R\x05slots\"\x84\x01\n\x0c\x46\x65\x61tureValue\x12\x14\n\x0c\x66\x65\x61ture_name\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\x12\x1c\n\x06values\x18\x03 \x03(\x0b\x32\x0c.sysml.Value\x12\x14\n\x0cmaterialized\x18\x04 \x01(\x08\x12\r\n\x05\x65rror\x18\x05 \x01(\t\";\n\x12InstantiateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"\x93\x01\n\x13InstantiateResponse\x12!\n\x08instance\x18\x01 \x01(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\"\n\tinstances\x18\x04 \x03(\x0b\x32\x0f.sysml.Instance\"\xba\x01\n\x14\x45xecuteActionRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x18\n\x10\x61\x63tion_symbol_id\x18\x02 \x01(\t\x12\x37\n\x06inputs\x18\x03 \x03(\x0b\x32\'.sysml.ExecuteActionRequest.InputsEntry\x1a;\n\x0bInputsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xc8\x01\n\x15\x45xecuteActionResponse\x12:\n\x07outputs\x18\x01 \x03(\x0b\x32).sysml.ExecuteActionResponse.OutputsEntry\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x1a<\n\x0cOutputsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"Z\n\x13\x45xecuteStateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1f\n\x17state_machine_symbol_id\x18\x02 \x01(\t\x12\x0e\n\x06\x65vents\x18\x03 \x03(\t\"\xee\x01\n\x14\x45xecuteStateResponse\x12\x16\n\x0estates_visited\x18\x01 \x03(\t\x12\x44\n\rfinal_context\x18\x02 \x03(\x0b\x32-.sysml.ExecuteStateResponse.FinalContextEntry\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x1a\x41\n\x11\x46inalContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xa0\x01\n\x0e\x43onvertRequest\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x14\n\nmodel_hash\x18\x06 \x01(\tH\x00\x12\x13\n\x0b\x66rom_format\x18\x03 \x01(\t\x12\x11\n\tto_format\x18\x04 \x01(\t\x12\x1e\n\x16tolerate_syntax_errors\x18\x05 \x01(\x08\x42\x08\n\x06source\"\xb4\x01\n\x0f\x43onvertResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x13\n\x0b\x66rom_format\x18\x02 \x01(\t\x12\x11\n\tto_format\x18\x03 \x01(\t\x12\r\n\x05\x65rror\x18\x04 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x14\n\x0c\x65xperimental\x18\x06 \x01(\x08\x12\x1b\n\x13\x65xperimental_notice\x18\x07 \x01(\t\"Q\n\x11\x41pplyEditsRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12(\n\noperations\x18\x02 \x03(\x0b\x32\x14.sysml.EditOperation\"\xbc\x01\n\rEditOperation\x12(\n\tset_value\x18\x01 \x01(\x0b\x32\x13.sysml.SetValueEditH\x00\x12#\n\x06rename\x18\x02 \x01(\x0b\x32\x11.sysml.RenameEditH\x00\x12*\n\nadd_member\x18\x03 \x01(\x0b\x32\x14.sysml.AddMemberEditH\x00\x12#\n\x06\x64\x65lete\x18\x04 \x01(\x0b\x32\x11.sysml.DeleteEditH\x00\x42\x0b\n\toperation\"\x82\x01\n\rAddMemberEdit\x12\r\n\x05owner\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0c\n\x04type\x18\x04 \x01(\t\x12\x14\n\x0cmultiplicity\x18\x05 \x01(\t\x12\r\n\x05value\x18\x06 \x01(\t\x12\x13\n\x0bspecializes\x18\x07 \x03(\t\"-\n\nDeleteEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\x0f\n\x07\x63\x61scade\x18\x02 \x01(\x08\"-\n\x0cSetValueEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\".\n\nRenameEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\x10\n\x08new_name\x18\x02 \x01(\t\"\xc2\x01\n\x12\x41pplyEditsResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12#\n\x07\x61pplied\x18\x02 \x03(\x0b\x32\x12.sysml.AppliedEdit\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12#\n\x07\x66\x61ilure\x18\x04 \x01(\x0e\x32\x12.sysml.EditFailure\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x1a\n\x12referring_elements\x18\x06 \x03(\t\"z\n\x0b\x41ppliedEdit\x12\x17\n\x0foperation_index\x18\x01 \x01(\x05\x12\x0e\n\x06target\x18\x02 \x01(\t\x12\x0e\n\x06offset\x18\x03 \x01(\x05\x12\x0e\n\x06length\x18\x04 \x01(\x05\x12\x10\n\x08old_text\x18\x05 \x01(\t\x12\x10\n\x08new_text\x18\x06 \x01(\t\"\xfd\x02\n\nSymbolInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0c\n\x04kind\x18\x03 \x01(\t\x12\x31\n\x08metadata\x18\x04 \x03(\x0b\x32\x1f.sysml.SymbolInfo.MetadataEntry\x12\x11\n\tchild_ids\x18\x05 \x03(\t\x12(\n\nattributes\x18\x06 \x03(\x0b\x32\x14.sysml.AttributeInfo\x12\"\n\ttype_info\x18\x07 \x01(\x0b\x32\x0f.sysml.TypeInfo\x12-\n\x0cmultiplicity\x18\x08 \x01(\x0b\x32\x17.sysml.MultiplicityInfo\x12.\n\x0fspecializations\x18\t \x03(\x0b\x32\x15.sysml.Specialization\x12#\n\x1bwithheld_library_attributes\x18\n \x01(\x05\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"X\n\x0eSpecialization\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x10\n\x08\x64\x65\x63lared\x18\x02 \x01(\t\x12\x11\n\ttarget_id\x18\x03 \x01(\t\x12\x13\n\x0btarget_kind\x18\x04 \x01(\t\"\x95\x01\n\x08TypeInfo\x12\x10\n\x08\x64\x65\x63lared\x18\x01 \x01(\t\x12\x13\n\x0bresolved_id\x18\x02 \x01(\t\x12\x15\n\rresolved_kind\x18\x03 \x01(\t\x12\x11\n\tprimitive\x18\x04 \x01(\t\x12\x18\n\x10primitive_source\x18\x05 \x01(\t\x12\x10\n\x08quantity\x18\x06 \x01(\x08\x12\x0c\n\x04unit\x18\x07 \x01(\t\"0\n\x10MultiplicityInfo\x12\r\n\x05lower\x18\x01 \x01(\t\x12\r\n\x05upper\x18\x02 \x01(\t\"V\n\rAttributeInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\x1b\n\x05value\x18\x03 \x01(\x0b\x32\x0c.sysml.Value\x12\x0c\n\x04unit\x18\x04 \x01(\t\"\x9b\x04\n\x05Value\x12\x13\n\tint_value\x18\x01 \x01(\x03H\x00\x12\x14\n\nreal_value\x18\x02 \x01(\x01H\x00\x12\x14\n\nbool_value\x18\x03 \x01(\x08H\x00\x12\x16\n\x0cstring_value\x18\x04 \x01(\tH\x00\x12\x15\n\x0binstance_id\x18\x05 \x01(\x03H\x00\x12(\n\x08sequence\x18\x06 \x01(\x0b\x32\x14.sysml.ValueSequenceH\x00\x12\x0e\n\x04null\x18\x07 \x01(\tH\x00\x12#\n\x08quantity\x18\x08 \x01(\x0b\x32\x0f.sysml.QuantityH\x00\x12*\n\x0c\x65num_literal\x18\t \x01(\x0b\x32\x12.sysml.EnumLiteralH\x00\x12\x0f\n\x05unset\x18\n \x01(\x08H\x00\x12!\n\x07\x63omplex\x18\x0b \x01(\x0b\x32\x0e.sysml.ComplexH\x00\x12\x1d\n\x05\x61rray\x18\x0c \x01(\x0b\x32\x0c.sysml.ArrayH\x00\x12\x1f\n\x06vector\x18\r \x01(\x0b\x32\r.sysml.VectorH\x00\x12\x30\n\x0fvector_quantity\x18\x0e \x01(\x0b\x32\x15.sysml.VectorQuantityH\x00\x12\x30\n\x0fmeasurement_ref\x18\x0f \x01(\x0b\x32\x15.sysml.MeasurementRefH\x00\x12\x12\n\x08infinity\x18\x10 \x01(\x08H\x00\x12#\n\x08\x66unction\x18\x11 \x01(\x0b\x32\x0f.sysml.FunctionH\x00\x42\x06\n\x04kind\",\n\x08\x46unction\x12\x0f\n\x07\x63\x61lc_id\x18\x01 \x01(\t\x12\x0f\n\x07self_id\x18\x02 \x01(\x03\";\n\x05\x41rray\x12\x12\n\ndimensions\x18\x01 \x03(\x03\x12\x1e\n\x08\x65lements\x18\x02 \x03(\x0b\x32\x0c.sysml.Value\"*\n\x06Vector\x12 \n\ncomponents\x18\x01 \x03(\x0b\x32\x0c.sysml.Value\"5\n\x0eVectorQuantity\x12#\n\ncomponents\x18\x01 \x03(\x0b\x32\x0f.sysml.Quantity\"*\n\x07\x43omplex\x12\x0c\n\x04real\x18\x01 \x01(\x01\x12\x11\n\timaginary\x18\x02 \x01(\x01\"G\n\x0b\x45numLiteral\x12\x12\n\nliteral_id\x18\x01 \x01(\t\x12\x16\n\x0e\x65numeration_id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\"/\n\rValueSequence\x12\x1e\n\x08\x65lements\x18\x01 \x03(\x0b\x32\x0c.sysml.Value\"|\n\x08Quantity\x12\x17\n\rint_magnitude\x18\x01 \x01(\x03H\x00\x12\x18\n\x0ereal_magnitude\x18\x02 \x01(\x01H\x00\x12\x0c\n\x04unit\x18\x03 \x01(\t\x12\"\n\tunit_term\x18\x04 \x01(\x0b\x32\x0f.sysml.UnitTermB\x0b\n\tmagnitude\"S\n\x0eMeasurementRef\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\"\n\tunit_term\x18\x02 \x01(\x0b\x32\x0f.sysml.UnitTerm\x12\x0f\n\x07unit_id\x18\x03 \x01(\t\"T\n\x08UnitTerm\x12\x11\n\tscale_num\x18\x01 \x01(\x01\x12\x11\n\tscale_den\x18\x02 \x01(\x01\x12\"\n\x07\x66\x61\x63tors\x18\x03 \x03(\x0b\x32\x11.sysml.UnitFactor\"/\n\nUnitFactor\x12\x0f\n\x07unit_id\x18\x01 \x01(\t\x12\x10\n\x08\x65xponent\x18\x02 \x01(\x01\"J\n\nDiagnostic\x12\x10\n\x08severity\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x04span\x18\x03 \x01(\x0b\x32\x0b.sysml.Span\"^\n\x04Span\x12\x0c\n\x04\x66ile\x18\x01 \x01(\t\x12\x12\n\nstart_line\x18\x02 \x01(\x05\x12\x11\n\tstart_col\x18\x03 \x01(\x05\x12\x10\n\x08\x65nd_line\x18\x04 \x01(\x05\x12\x0f\n\x07\x65nd_col\x18\x05 \x01(\x05\"\x13\n\x11ServerInfoRequest\";\n\x12ServerInfoResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x02 \x03(\t\"S\n\x0cQueryRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1b\n\x05query\x18\x02 \x01(\x0b\x32\x0c.sysml.Query\x12\x12\n\noslc_query\x18\x03 \x01(\t\"<\n\rQueryResponse\x12+\n\x08\x65lements\x18\x01 \x03(\x0b\x32\x19.sysml.QueryResultElement\"H\n\x05Query\x12\r\n\x05scope\x18\x01 \x03(\t\x12\x0e\n\x06select\x18\x02 \x03(\t\x12 \n\x05where\x18\x03 \x01(\x0b\x32\x11.sysml.Constraint\"|\n\nConstraint\x12/\n\tprimitive\x18\x01 \x01(\x0b\x32\x1a.sysml.PrimitiveConstraintH\x00\x12/\n\tcomposite\x18\x02 \x01(\x0b\x32\x1a.sysml.CompositeConstraintH\x00\x42\x0c\n\nconstraint\"s\n\x13PrimitiveConstraint\x12\x0f\n\x07inverse\x18\x01 \x01(\x08\x12\x10\n\x08property\x18\x02 \x01(\t\x12*\n\x08operator\x18\x03 \x01(\x0e\x32\x18.sysml.PrimitiveOperator\x12\r\n\x05value\x18\x04 \x03(\t\"h\n\x13\x43ompositeConstraint\x12*\n\x08operator\x18\x01 \x01(\x0e\x32\x18.sysml.CompositeOperator\x12%\n\nconstraint\x18\x02 \x03(\x0b\x32\x11.sysml.Constraint\"\xa0\x01\n\x12QueryResultElement\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12=\n\nproperties\x18\x03 \x03(\x0b\x32).sysml.QueryResultElement.PropertiesEntry\x1a\x31\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"s\n\nSweepRange\x12\x11\n\tparameter\x18\x01 \x01(\t\x12\x1b\n\x05start\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\x12\x19\n\x03\x65nd\x18\x03 \x01(\x0b\x32\x0c.sysml.Value\x12\x1a\n\x04step\x18\x04 \x01(\x0b\x32\x0c.sysml.Value\"\xc0\x02\n\x0fRunSweepRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\x12\x1f\n\targuments\x18\x04 \x03(\x0b\x32\x0c.sysml.Value\x12\x43\n\x0fnamed_arguments\x18\x05 \x03(\x0b\x32*.sysml.RunSweepRequest.NamedArgumentsEntry\x12!\n\x06ranges\x18\x06 \x03(\x0b\x32\x11.sysml.SweepRange\x12\x0f\n\x07samples\x18\x07 \x01(\x03\x12\x0c\n\x04seed\x18\x08 \x01(\x04\x1a\x43\n\x13NamedArgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xc8\x01\n\x08SweepRow\x12!\n\x06inputs\x18\x01 \x03(\x0b\x32\x11.sysml.CalcOutput\x12\"\n\x07outputs\x18\x02 \x03(\x0b\x32\x11.sysml.CalcOutput\x12 \n\x08verdicts\x18\x03 \x03(\x0b\x32\x0e.sysml.Verdict\x12\x16\n\x0e\x65lapsed_micros\x18\x04 \x01(\x03\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12,\n\x0e\x66\x61ilure_reason\x18\x06 \x01(\x0e\x32\x14.sysml.FailureReason\"\xed\x01\n\x10RunSweepResponse\x12\x1d\n\x04rows\x18\x01 \x03(\x0b\x32\x0f.sysml.SweepRow\x12\x12\n\nparameters\x18\x02 \x03(\t\x12\x0f\n\x07sampled\x18\x03 \x01(\x08\x12\x0c\n\x04seed\x18\x04 \x01(\x04\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x06 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x07 \x01(\x0e\x32\x14.sysml.FailureReason\x12\"\n\tinstances\x18\x08 \x03(\x0b\x32\x0f.sysml.Instance\"n\n\x17RunDocumentQueryRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x10\n\x08query_id\x18\x02 \x01(\t\x12-\n\x08\x62indings\x18\x03 \x03(\x0b\x32\x1b.sysml.DocumentQueryBinding\"O\n\x14\x44ocumentQueryBinding\x12\x11\n\tparameter\x18\x01 \x01(\t\x12$\n\x06values\x18\x02 \x03(\x0b\x32\x14.sysml.DocumentValue\"\xd5\x01\n\rDocumentValue\x12\x14\n\nelement_id\x18\x01 \x01(\tH\x00\x12\x16\n\x0cstring_value\x18\x02 \x01(\tH\x00\x12\x13\n\tint_value\x18\x03 \x01(\x03H\x00\x12\x14\n\nreal_value\x18\x04 \x01(\x01H\x00\x12\x14\n\nbool_value\x18\x05 \x01(\x08H\x00\x12\x12\n\x08infinity\x18\x06 \x01(\x08H\x00\x12#\n\x08quantity\x18\x08 \x01(\x0b\x32\x0f.sysml.QuantityH\x00\x12\x14\n\x0c\x65lement_type\x18\x07 \x01(\tB\x06\n\x04kind\"#\n\x13\x44ocumentQueryColumn\x12\x0c\n\x04name\x18\x01 \x01(\t\"9\n\x11\x44ocumentQueryCell\x12$\n\x06values\x18\x01 \x03(\x0b\x32\x14.sysml.DocumentValue\"b\n\x10\x44ocumentQueryRow\x12%\n\x07\x65lement\x18\x01 \x01(\x0b\x32\x14.sysml.DocumentValue\x12\'\n\x05\x63\x65lls\x18\x02 \x03(\x0b\x32\x18.sysml.DocumentQueryCell\"n\n\x18RunDocumentQueryResponse\x12+\n\x07\x63olumns\x18\x01 \x03(\x0b\x32\x1a.sysml.DocumentQueryColumn\x12%\n\x04rows\x18\x02 \x03(\x0b\x32\x17.sysml.DocumentQueryRow\"@\n\x15RenderDocumentRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x02 \x01(\t\"*\n\x16RenderDocumentResponse\x12\x10\n\x08markdown\x18\x01 \x01(\t*\x93\x01\n\rFailureReason\x12\x1e\n\x1a\x46\x41ILURE_REASON_UNSPECIFIED\x10\x00\x12\x1d\n\x19\x46\x41ILURE_REASON_EVALUATION\x10\x01\x12\x1d\n\x19\x46\x41ILURE_REASON_WRONG_KIND\x10\x02\x12$\n FAILURE_REASON_AMBIGUOUS_SUBJECT\x10\x03*\x9d\x04\n\x0b\x45\x64itFailure\x12\x1c\n\x18\x45\x44IT_FAILURE_UNSPECIFIED\x10\x00\x12\x1e\n\x1a\x45\x44IT_FAILURE_NO_OPERATIONS\x10\x01\x12\x1f\n\x1b\x45\x44IT_FAILURE_UNKNOWN_TARGET\x10\x02\x12!\n\x1d\x45\x44IT_FAILURE_AMBIGUOUS_TARGET\x10\x03\x12\x1b\n\x17\x45\x44IT_FAILURE_NOT_VALUED\x10\x04\x12\x1e\n\x1a\x45\x44IT_FAILURE_INVALID_VALUE\x10\x05\x12\x1d\n\x19\x45\x44IT_FAILURE_INVALID_NAME\x10\x06\x12\x1a\n\x16\x45\x44IT_FAILURE_NOT_NAMED\x10\x07\x12\"\n\x1e\x45\x44IT_FAILURE_RENAME_REFERENCED\x10\x08\x12\"\n\x1e\x45\x44IT_FAILURE_OVERLAPPING_EDITS\x10\t\x12\x1f\n\x1b\x45\x44IT_FAILURE_RESULT_INVALID\x10\n\x12\x1e\n\x1a\x45\x44IT_FAILURE_OWNER_UNKNOWN\x10\x0b\x12$\n EDIT_FAILURE_OWNER_NOT_NAMESPACE\x10\x0c\x12\x1d\n\x19\x45\x44IT_FAILURE_ILLEGAL_KIND\x10\r\x12\"\n\x1e\x45\x44IT_FAILURE_MEMBER_NAME_TAKEN\x10\x0e\x12\"\n\x1e\x45\x44IT_FAILURE_DELETE_REFERENCED\x10\x0f*\x92\x01\n\x11PrimitiveOperator\x12\"\n\x1ePRIMITIVE_OPERATOR_UNSPECIFIED\x10\x00\x12\x1c\n\x18PRIMITIVE_OPERATOR_EQUAL\x10\x01\x12\x1e\n\x1aPRIMITIVE_OPERATOR_GREATER\x10\x02\x12\x1b\n\x17PRIMITIVE_OPERATOR_LESS\x10\x03*n\n\x11\x43ompositeOperator\x12\"\n\x1e\x43OMPOSITE_OPERATOR_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x43OMPOSITE_OPERATOR_AND\x10\x01\x12\x19\n\x15\x43OMPOSITE_OPERATOR_OR\x10\x02\x32\xa4\x0b\n\x0cSysMLService\x12\x44\n\rGetServerInfo\x12\x18.sysml.ServerInfoRequest\x1a\x19.sysml.ServerInfoResponse\x12>\n\tParseFile\x12\x17.sysml.ParseFileRequest\x1a\x18.sysml.ParseFileResponse\x12G\n\x0cParseSources\x12\x1a.sysml.ParseSourcesRequest\x1a\x1b.sysml.ParseSourcesResponse\x12;\n\tGetSymbol\x12\x17.sysml.GetSymbolRequest\x1a\x15.sysml.SymbolResponse\x12G\n\x0eGetDiagnostics\x12\x19.sysml.DiagnosticsRequest\x1a\x1a.sysml.DiagnosticsResponse\x12;\n\x08\x45valuate\x12\x16.sysml.EvaluateRequest\x1a\x17.sysml.EvaluateResponse\x12\x44\n\x0bInstantiate\x12\x19.sysml.InstantiateRequest\x1a\x1a.sysml.InstantiateResponse\x12J\n\rExecuteAction\x12\x1b.sysml.ExecuteActionRequest\x1a\x1c.sysml.ExecuteActionResponse\x12G\n\x0c\x45xecuteState\x12\x1a.sysml.ExecuteStateRequest\x1a\x1b.sysml.ExecuteStateResponse\x12\x38\n\x07\x43onvert\x12\x15.sysml.ConvertRequest\x1a\x16.sysml.ConvertResponse\x12\x41\n\nApplyEdits\x12\x18.sysml.ApplyEditsRequest\x1a\x19.sysml.ApplyEditsResponse\x12S\n\x10VerifyConstraint\x12\x1e.sysml.VerifyConstraintRequest\x1a\x1f.sysml.VerifyConstraintResponse\x12V\n\x11VerifyRequirement\x12\x1f.sysml.VerifyRequirementRequest\x1a .sysml.VerifyRequirementResponse\x12Y\n\x12VerifySatisfaction\x12 .sysml.VerifySatisfactionRequest\x1a!.sysml.VerifySatisfactionResponse\x12G\n\x0c\x45valuateCalc\x12\x1a.sysml.EvaluateCalcRequest\x1a\x1b.sysml.EvaluateCalcResponse\x12\x44\n\x0bRunAnalysis\x12\x19.sysml.RunAnalysisRequest\x1a\x1a.sysml.RunAnalysisResponse\x12;\n\x08RunSweep\x12\x16.sysml.RunSweepRequest\x1a\x17.sysml.RunSweepResponse\x12\x32\n\x05Query\x12\x13.sysml.QueryRequest\x1a\x14.sysml.QueryResponse\x12S\n\x10RunDocumentQuery\x12\x1e.sysml.RunDocumentQueryRequest\x1a\x1f.sysml.RunDocumentQueryResponse\x12M\n\x0eRenderDocument\x12\x1c.sysml.RenderDocumentRequest\x1a\x1d.sysml.RenderDocumentResponseB*Z(github.com/Open-MBEE/OpenSysML/api/protob\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bsysml.proto\x12\x05sysml\"\xe2\x01\n\x07Verdict\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x12\n\nelement_id\x18\x02 \x01(\t\x12\x0f\n\x07\x65lement\x18\x03 \x01(\t\x12\r\n\x05holds\x18\x04 \x01(\x08\x12\x11\n\tcondition\x18\x05 \x01(\t\x12\x13\n\x0binstance_id\x18\x06 \x01(\x03\x12\x18\n\x10instance_type_id\x18\x07 \x01(\t\x12\r\n\x05\x65rror\x18\x08 \x01(\t\x12,\n\x0e\x66\x61ilure_reason\x18\t \x01(\x0e\x32\x14.sysml.FailureReason\x12\x16\n\x0erequirement_id\x18\n \x01(\t\"[\n\x17VerifyConstraintRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\"\x96\x01\n\x18VerifyConstraintResponse\x12\x1f\n\x07verdict\x18\x01 \x01(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\"\\\n\x18VerifyRequirementRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\"m\n\x13VerificationVerdict\x12\x0f\n\x07\x63\x61se_id\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x0e\n\x06\x64\x65tail\x18\x03 \x01(\t\x12\x0f\n\x07subcase\x18\x04 \x01(\x08\x12\x16\n\x0erequirement_id\x18\x05 \x01(\t\"\xd2\x01\n\x19VerifyRequirementResponse\x12\x1f\n\x07verdict\x18\x01 \x01(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x39\n\x15verification_verdicts\x18\x05 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"B\n\x19VerifySatisfactionRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"\x82\x02\n\x1aVerifySatisfactionResponse\x12 \n\x08verdicts\x18\x01 \x03(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x02 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x05 \x01(\x0e\x32\x14.sysml.FailureReason\x12\x39\n\x15verification_verdicts\x18\x06 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"]\n\x13\x45valuateCalcRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x1f\n\targuments\x18\x03 \x03(\x0b\x32\x0c.sysml.Value\"\xbd\x01\n\x14\x45valuateCalcResponse\x12\x1c\n\x06result\x18\x01 \x01(\x0b\x32\x0c.sysml.Value\x12\"\n\x07outputs\x18\x02 \x03(\x0b\x32\x11.sysml.CalcOutput\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x05 \x01(\x0e\x32\x14.sysml.FailureReason\"7\n\nCalcOutput\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\"\x84\x02\n\x12RunAnalysisRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\x12\x1f\n\targuments\x18\x04 \x03(\x0b\x32\x0c.sysml.Value\x12\x46\n\x0fnamed_arguments\x18\x05 \x03(\x0b\x32-.sysml.RunAnalysisRequest.NamedArgumentsEntry\x1a\x43\n\x13NamedArgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\x9f\x02\n\x13RunAnalysisResponse\x12\"\n\x07outputs\x18\x01 \x03(\x0b\x32\x11.sysml.CalcOutput\x12 \n\x08verdicts\x18\x02 \x03(\x0b\x32\x0e.sysml.Verdict\x12\"\n\tinstances\x18\x03 \x03(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x04 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x06 \x01(\x0e\x32\x14.sysml.FailureReason\x12\x39\n\x15verification_verdicts\x18\x07 \x03(\x0b\x32\x1a.sysml.VerificationVerdict\"\x8c\x01\n\x10ParseFileRequest\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x18\n\x0c\x63ontent_hash\x18\x03 \x01(\tB\x02\x18\x01\x12\x10\n\x08language\x18\x04 \x01(\t\x12\x1a\n\x12strict_conformance\x18\x05 \x01(\x08\x42\x08\n\x06source\"b\n\x0eSourceDocument\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x10\n\x08language\x18\x03 \x01(\t\x12\x0c\n\x04name\x18\x04 \x01(\tB\x08\n\x06source\"[\n\x13ParseSourcesRequest\x12(\n\tdocuments\x18\x01 \x03(\x0b\x32\x15.sysml.SourceDocument\x12\x1a\n\x12strict_conformance\x18\x02 \x01(\x08\"\x83\x01\n\x14ParseSourcesResponse\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12 \n\x05roots\x18\x02 \x03(\x0b\x32\x11.sysml.SymbolInfo\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"\x7f\n\x11ParseFileResponse\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1f\n\x04root\x18\x02 \x01(\x0b\x32\x11.sysml.SymbolInfo\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"9\n\x10GetSymbolRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"B\n\x0eSymbolResponse\x12!\n\x06symbol\x18\x01 \x01(\x0b\x32\x11.sysml.SymbolInfo\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"(\n\x12\x44iagnosticsRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\"L\n\x13\x44iagnosticsResponse\x12&\n\x0b\x64iagnostics\x18\x01 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"o\n\x0f\x45valuateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x12\n\nexpression\x18\x02 \x01(\t\x12\x19\n\x11\x63ontext_symbol_id\x18\x03 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x04 \x01(\t\"g\n\x10\x45valuateResponse\x12\x1c\n\x06result\x18\x01 \x01(\x0b\x32\x0c.sysml.Value\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\"\xc2\x01\n\x08Instance\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x16\n\x0etype_symbol_id\x18\x02 \x01(\t\x12:\n\x0e\x66\x65\x61ture_values\x18\x04 \x03(\x0b\x32\".sysml.Instance.FeatureValuesEntry\x1aI\n\x12\x46\x65\x61tureValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.sysml.FeatureValue:\x02\x38\x01J\x04\x08\x03\x10\x04R\x05slots\"\x84\x01\n\x0c\x46\x65\x61tureValue\x12\x14\n\x0c\x66\x65\x61ture_name\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\x12\x1c\n\x06values\x18\x03 \x03(\x0b\x32\x0c.sysml.Value\x12\x14\n\x0cmaterialized\x18\x04 \x01(\x08\x12\r\n\x05\x65rror\x18\x05 \x01(\t\";\n\x12InstantiateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\"\x93\x01\n\x13InstantiateResponse\x12!\n\x08instance\x18\x01 \x01(\x0b\x32\x0f.sysml.Instance\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\"\n\tinstances\x18\x04 \x03(\x0b\x32\x0f.sysml.Instance\"\xba\x01\n\x14\x45xecuteActionRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x18\n\x10\x61\x63tion_symbol_id\x18\x02 \x01(\t\x12\x37\n\x06inputs\x18\x03 \x03(\x0b\x32\'.sysml.ExecuteActionRequest.InputsEntry\x1a;\n\x0bInputsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xc8\x01\n\x15\x45xecuteActionResponse\x12:\n\x07outputs\x18\x01 \x03(\x0b\x32).sysml.ExecuteActionResponse.OutputsEntry\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x03 \x03(\x0b\x32\x11.sysml.Diagnostic\x1a<\n\x0cOutputsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"Z\n\x13\x45xecuteStateRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1f\n\x17state_machine_symbol_id\x18\x02 \x01(\t\x12\x0e\n\x06\x65vents\x18\x03 \x03(\t\"\xee\x01\n\x14\x45xecuteStateResponse\x12\x16\n\x0estates_visited\x18\x01 \x03(\t\x12\x44\n\rfinal_context\x18\x02 \x03(\x0b\x32-.sysml.ExecuteStateResponse.FinalContextEntry\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x04 \x03(\x0b\x32\x11.sysml.Diagnostic\x1a\x41\n\x11\x46inalContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xa0\x01\n\x0e\x43onvertRequest\x12\x13\n\tfile_path\x18\x01 \x01(\tH\x00\x12\x11\n\x07\x63ontent\x18\x02 \x01(\tH\x00\x12\x14\n\nmodel_hash\x18\x06 \x01(\tH\x00\x12\x13\n\x0b\x66rom_format\x18\x03 \x01(\t\x12\x11\n\tto_format\x18\x04 \x01(\t\x12\x1e\n\x16tolerate_syntax_errors\x18\x05 \x01(\x08\x42\x08\n\x06source\"\xb4\x01\n\x0f\x43onvertResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x13\n\x0b\x66rom_format\x18\x02 \x01(\t\x12\x11\n\tto_format\x18\x03 \x01(\t\x12\r\n\x05\x65rror\x18\x04 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x14\n\x0c\x65xperimental\x18\x06 \x01(\x08\x12\x1b\n\x13\x65xperimental_notice\x18\x07 \x01(\t\"Q\n\x11\x41pplyEditsRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12(\n\noperations\x18\x02 \x03(\x0b\x32\x14.sysml.EditOperation\"\xbc\x01\n\rEditOperation\x12(\n\tset_value\x18\x01 \x01(\x0b\x32\x13.sysml.SetValueEditH\x00\x12#\n\x06rename\x18\x02 \x01(\x0b\x32\x11.sysml.RenameEditH\x00\x12*\n\nadd_member\x18\x03 \x01(\x0b\x32\x14.sysml.AddMemberEditH\x00\x12#\n\x06\x64\x65lete\x18\x04 \x01(\x0b\x32\x11.sysml.DeleteEditH\x00\x42\x0b\n\toperation\"\x82\x01\n\rAddMemberEdit\x12\r\n\x05owner\x18\x01 \x01(\t\x12\x0c\n\x04kind\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0c\n\x04type\x18\x04 \x01(\t\x12\x14\n\x0cmultiplicity\x18\x05 \x01(\t\x12\r\n\x05value\x18\x06 \x01(\t\x12\x13\n\x0bspecializes\x18\x07 \x03(\t\"-\n\nDeleteEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\x0f\n\x07\x63\x61scade\x18\x02 \x01(\x08\"-\n\x0cSetValueEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\".\n\nRenameEdit\x12\x0e\n\x06target\x18\x01 \x01(\t\x12\x10\n\x08new_name\x18\x02 \x01(\t\"\xc2\x01\n\x12\x41pplyEditsResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12#\n\x07\x61pplied\x18\x02 \x03(\x0b\x32\x12.sysml.AppliedEdit\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12#\n\x07\x66\x61ilure\x18\x04 \x01(\x0e\x32\x12.sysml.EditFailure\x12&\n\x0b\x64iagnostics\x18\x05 \x03(\x0b\x32\x11.sysml.Diagnostic\x12\x1a\n\x12referring_elements\x18\x06 \x03(\t\"z\n\x0b\x41ppliedEdit\x12\x17\n\x0foperation_index\x18\x01 \x01(\x05\x12\x0e\n\x06target\x18\x02 \x01(\t\x12\x0e\n\x06offset\x18\x03 \x01(\x05\x12\x0e\n\x06length\x18\x04 \x01(\x05\x12\x10\n\x08old_text\x18\x05 \x01(\t\x12\x10\n\x08new_text\x18\x06 \x01(\t\"\xfd\x02\n\nSymbolInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0c\n\x04kind\x18\x03 \x01(\t\x12\x31\n\x08metadata\x18\x04 \x03(\x0b\x32\x1f.sysml.SymbolInfo.MetadataEntry\x12\x11\n\tchild_ids\x18\x05 \x03(\t\x12(\n\nattributes\x18\x06 \x03(\x0b\x32\x14.sysml.AttributeInfo\x12\"\n\ttype_info\x18\x07 \x01(\x0b\x32\x0f.sysml.TypeInfo\x12-\n\x0cmultiplicity\x18\x08 \x01(\x0b\x32\x17.sysml.MultiplicityInfo\x12.\n\x0fspecializations\x18\t \x03(\x0b\x32\x15.sysml.Specialization\x12#\n\x1bwithheld_library_attributes\x18\n \x01(\x05\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"X\n\x0eSpecialization\x12\x0c\n\x04kind\x18\x01 \x01(\t\x12\x10\n\x08\x64\x65\x63lared\x18\x02 \x01(\t\x12\x11\n\ttarget_id\x18\x03 \x01(\t\x12\x13\n\x0btarget_kind\x18\x04 \x01(\t\"\x95\x01\n\x08TypeInfo\x12\x10\n\x08\x64\x65\x63lared\x18\x01 \x01(\t\x12\x13\n\x0bresolved_id\x18\x02 \x01(\t\x12\x15\n\rresolved_kind\x18\x03 \x01(\t\x12\x11\n\tprimitive\x18\x04 \x01(\t\x12\x18\n\x10primitive_source\x18\x05 \x01(\t\x12\x10\n\x08quantity\x18\x06 \x01(\x08\x12\x0c\n\x04unit\x18\x07 \x01(\t\"0\n\x10MultiplicityInfo\x12\r\n\x05lower\x18\x01 \x01(\t\x12\r\n\x05upper\x18\x02 \x01(\t\"V\n\rAttributeInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\x1b\n\x05value\x18\x03 \x01(\x0b\x32\x0c.sysml.Value\x12\x0c\n\x04unit\x18\x04 \x01(\t\"\x9b\x04\n\x05Value\x12\x13\n\tint_value\x18\x01 \x01(\x03H\x00\x12\x14\n\nreal_value\x18\x02 \x01(\x01H\x00\x12\x14\n\nbool_value\x18\x03 \x01(\x08H\x00\x12\x16\n\x0cstring_value\x18\x04 \x01(\tH\x00\x12\x15\n\x0binstance_id\x18\x05 \x01(\x03H\x00\x12(\n\x08sequence\x18\x06 \x01(\x0b\x32\x14.sysml.ValueSequenceH\x00\x12\x0e\n\x04null\x18\x07 \x01(\tH\x00\x12#\n\x08quantity\x18\x08 \x01(\x0b\x32\x0f.sysml.QuantityH\x00\x12*\n\x0c\x65num_literal\x18\t \x01(\x0b\x32\x12.sysml.EnumLiteralH\x00\x12\x0f\n\x05unset\x18\n \x01(\x08H\x00\x12!\n\x07\x63omplex\x18\x0b \x01(\x0b\x32\x0e.sysml.ComplexH\x00\x12\x1d\n\x05\x61rray\x18\x0c \x01(\x0b\x32\x0c.sysml.ArrayH\x00\x12\x1f\n\x06vector\x18\r \x01(\x0b\x32\r.sysml.VectorH\x00\x12\x30\n\x0fvector_quantity\x18\x0e \x01(\x0b\x32\x15.sysml.VectorQuantityH\x00\x12\x30\n\x0fmeasurement_ref\x18\x0f \x01(\x0b\x32\x15.sysml.MeasurementRefH\x00\x12\x12\n\x08infinity\x18\x10 \x01(\x08H\x00\x12#\n\x08\x66unction\x18\x11 \x01(\x0b\x32\x0f.sysml.FunctionH\x00\x42\x06\n\x04kind\",\n\x08\x46unction\x12\x0f\n\x07\x63\x61lc_id\x18\x01 \x01(\t\x12\x0f\n\x07self_id\x18\x02 \x01(\x03\";\n\x05\x41rray\x12\x12\n\ndimensions\x18\x01 \x03(\x03\x12\x1e\n\x08\x65lements\x18\x02 \x03(\x0b\x32\x0c.sysml.Value\"*\n\x06Vector\x12 \n\ncomponents\x18\x01 \x03(\x0b\x32\x0c.sysml.Value\"5\n\x0eVectorQuantity\x12#\n\ncomponents\x18\x01 \x03(\x0b\x32\x0f.sysml.Quantity\"*\n\x07\x43omplex\x12\x0c\n\x04real\x18\x01 \x01(\x01\x12\x11\n\timaginary\x18\x02 \x01(\x01\"G\n\x0b\x45numLiteral\x12\x12\n\nliteral_id\x18\x01 \x01(\t\x12\x16\n\x0e\x65numeration_id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\"/\n\rValueSequence\x12\x1e\n\x08\x65lements\x18\x01 \x03(\x0b\x32\x0c.sysml.Value\"|\n\x08Quantity\x12\x17\n\rint_magnitude\x18\x01 \x01(\x03H\x00\x12\x18\n\x0ereal_magnitude\x18\x02 \x01(\x01H\x00\x12\x0c\n\x04unit\x18\x03 \x01(\t\x12\"\n\tunit_term\x18\x04 \x01(\x0b\x32\x0f.sysml.UnitTermB\x0b\n\tmagnitude\"S\n\x0eMeasurementRef\x12\x0c\n\x04unit\x18\x01 \x01(\t\x12\"\n\tunit_term\x18\x02 \x01(\x0b\x32\x0f.sysml.UnitTerm\x12\x0f\n\x07unit_id\x18\x03 \x01(\t\"T\n\x08UnitTerm\x12\x11\n\tscale_num\x18\x01 \x01(\x01\x12\x11\n\tscale_den\x18\x02 \x01(\x01\x12\"\n\x07\x66\x61\x63tors\x18\x03 \x03(\x0b\x32\x11.sysml.UnitFactor\"/\n\nUnitFactor\x12\x0f\n\x07unit_id\x18\x01 \x01(\t\x12\x10\n\x08\x65xponent\x18\x02 \x01(\x01\"X\n\nDiagnostic\x12\x10\n\x08severity\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x04span\x18\x03 \x01(\x0b\x32\x0b.sysml.Span\x12\x0c\n\x04\x63ode\x18\x04 \x01(\t\"^\n\x04Span\x12\x0c\n\x04\x66ile\x18\x01 \x01(\t\x12\x12\n\nstart_line\x18\x02 \x01(\x05\x12\x11\n\tstart_col\x18\x03 \x01(\x05\x12\x10\n\x08\x65nd_line\x18\x04 \x01(\x05\x12\x0f\n\x07\x65nd_col\x18\x05 \x01(\x05\"\x13\n\x11ServerInfoRequest\";\n\x12ServerInfoResponse\x12\x0f\n\x07version\x18\x01 \x01(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x02 \x03(\t\"S\n\x0cQueryRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x1b\n\x05query\x18\x02 \x01(\x0b\x32\x0c.sysml.Query\x12\x12\n\noslc_query\x18\x03 \x01(\t\"<\n\rQueryResponse\x12+\n\x08\x65lements\x18\x01 \x03(\x0b\x32\x19.sysml.QueryResultElement\"H\n\x05Query\x12\r\n\x05scope\x18\x01 \x03(\t\x12\x0e\n\x06select\x18\x02 \x03(\t\x12 \n\x05where\x18\x03 \x01(\x0b\x32\x11.sysml.Constraint\"|\n\nConstraint\x12/\n\tprimitive\x18\x01 \x01(\x0b\x32\x1a.sysml.PrimitiveConstraintH\x00\x12/\n\tcomposite\x18\x02 \x01(\x0b\x32\x1a.sysml.CompositeConstraintH\x00\x42\x0c\n\nconstraint\"s\n\x13PrimitiveConstraint\x12\x0f\n\x07inverse\x18\x01 \x01(\x08\x12\x10\n\x08property\x18\x02 \x01(\t\x12*\n\x08operator\x18\x03 \x01(\x0e\x32\x18.sysml.PrimitiveOperator\x12\r\n\x05value\x18\x04 \x03(\t\"h\n\x13\x43ompositeConstraint\x12*\n\x08operator\x18\x01 \x01(\x0e\x32\x18.sysml.CompositeOperator\x12%\n\nconstraint\x18\x02 \x03(\x0b\x32\x11.sysml.Constraint\"\xa0\x01\n\x12QueryResultElement\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12=\n\nproperties\x18\x03 \x03(\x0b\x32).sysml.QueryResultElement.PropertiesEntry\x1a\x31\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"s\n\nSweepRange\x12\x11\n\tparameter\x18\x01 \x01(\t\x12\x1b\n\x05start\x18\x02 \x01(\x0b\x32\x0c.sysml.Value\x12\x19\n\x03\x65nd\x18\x03 \x01(\x0b\x32\x0c.sysml.Value\x12\x1a\n\x04step\x18\x04 \x01(\x0b\x32\x0c.sysml.Value\"\xc0\x02\n\x0fRunSweepRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x11\n\tsymbol_id\x18\x02 \x01(\t\x12\x19\n\x11subject_symbol_id\x18\x03 \x01(\t\x12\x1f\n\targuments\x18\x04 \x03(\x0b\x32\x0c.sysml.Value\x12\x43\n\x0fnamed_arguments\x18\x05 \x03(\x0b\x32*.sysml.RunSweepRequest.NamedArgumentsEntry\x12!\n\x06ranges\x18\x06 \x03(\x0b\x32\x11.sysml.SweepRange\x12\x0f\n\x07samples\x18\x07 \x01(\x03\x12\x0c\n\x04seed\x18\x08 \x01(\x04\x1a\x43\n\x13NamedArgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.sysml.Value:\x02\x38\x01\"\xc8\x01\n\x08SweepRow\x12!\n\x06inputs\x18\x01 \x03(\x0b\x32\x11.sysml.CalcOutput\x12\"\n\x07outputs\x18\x02 \x03(\x0b\x32\x11.sysml.CalcOutput\x12 \n\x08verdicts\x18\x03 \x03(\x0b\x32\x0e.sysml.Verdict\x12\x16\n\x0e\x65lapsed_micros\x18\x04 \x01(\x03\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12,\n\x0e\x66\x61ilure_reason\x18\x06 \x01(\x0e\x32\x14.sysml.FailureReason\"\xed\x01\n\x10RunSweepResponse\x12\x1d\n\x04rows\x18\x01 \x03(\x0b\x32\x0f.sysml.SweepRow\x12\x12\n\nparameters\x18\x02 \x03(\t\x12\x0f\n\x07sampled\x18\x03 \x01(\x08\x12\x0c\n\x04seed\x18\x04 \x01(\x04\x12\r\n\x05\x65rror\x18\x05 \x01(\t\x12&\n\x0b\x64iagnostics\x18\x06 \x03(\x0b\x32\x11.sysml.Diagnostic\x12,\n\x0e\x66\x61ilure_reason\x18\x07 \x01(\x0e\x32\x14.sysml.FailureReason\x12\"\n\tinstances\x18\x08 \x03(\x0b\x32\x0f.sysml.Instance\"n\n\x17RunDocumentQueryRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x10\n\x08query_id\x18\x02 \x01(\t\x12-\n\x08\x62indings\x18\x03 \x03(\x0b\x32\x1b.sysml.DocumentQueryBinding\"O\n\x14\x44ocumentQueryBinding\x12\x11\n\tparameter\x18\x01 \x01(\t\x12$\n\x06values\x18\x02 \x03(\x0b\x32\x14.sysml.DocumentValue\"\xd5\x01\n\rDocumentValue\x12\x14\n\nelement_id\x18\x01 \x01(\tH\x00\x12\x16\n\x0cstring_value\x18\x02 \x01(\tH\x00\x12\x13\n\tint_value\x18\x03 \x01(\x03H\x00\x12\x14\n\nreal_value\x18\x04 \x01(\x01H\x00\x12\x14\n\nbool_value\x18\x05 \x01(\x08H\x00\x12\x12\n\x08infinity\x18\x06 \x01(\x08H\x00\x12#\n\x08quantity\x18\x08 \x01(\x0b\x32\x0f.sysml.QuantityH\x00\x12\x14\n\x0c\x65lement_type\x18\x07 \x01(\tB\x06\n\x04kind\"#\n\x13\x44ocumentQueryColumn\x12\x0c\n\x04name\x18\x01 \x01(\t\"9\n\x11\x44ocumentQueryCell\x12$\n\x06values\x18\x01 \x03(\x0b\x32\x14.sysml.DocumentValue\"b\n\x10\x44ocumentQueryRow\x12%\n\x07\x65lement\x18\x01 \x01(\x0b\x32\x14.sysml.DocumentValue\x12\'\n\x05\x63\x65lls\x18\x02 \x03(\x0b\x32\x18.sysml.DocumentQueryCell\"n\n\x18RunDocumentQueryResponse\x12+\n\x07\x63olumns\x18\x01 \x03(\x0b\x32\x1a.sysml.DocumentQueryColumn\x12%\n\x04rows\x18\x02 \x03(\x0b\x32\x17.sysml.DocumentQueryRow\"@\n\x15RenderDocumentRequest\x12\x12\n\nmodel_hash\x18\x01 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x02 \x01(\t\"*\n\x16RenderDocumentResponse\x12\x10\n\x08markdown\x18\x01 \x01(\t*\x93\x01\n\rFailureReason\x12\x1e\n\x1a\x46\x41ILURE_REASON_UNSPECIFIED\x10\x00\x12\x1d\n\x19\x46\x41ILURE_REASON_EVALUATION\x10\x01\x12\x1d\n\x19\x46\x41ILURE_REASON_WRONG_KIND\x10\x02\x12$\n FAILURE_REASON_AMBIGUOUS_SUBJECT\x10\x03*\x9d\x04\n\x0b\x45\x64itFailure\x12\x1c\n\x18\x45\x44IT_FAILURE_UNSPECIFIED\x10\x00\x12\x1e\n\x1a\x45\x44IT_FAILURE_NO_OPERATIONS\x10\x01\x12\x1f\n\x1b\x45\x44IT_FAILURE_UNKNOWN_TARGET\x10\x02\x12!\n\x1d\x45\x44IT_FAILURE_AMBIGUOUS_TARGET\x10\x03\x12\x1b\n\x17\x45\x44IT_FAILURE_NOT_VALUED\x10\x04\x12\x1e\n\x1a\x45\x44IT_FAILURE_INVALID_VALUE\x10\x05\x12\x1d\n\x19\x45\x44IT_FAILURE_INVALID_NAME\x10\x06\x12\x1a\n\x16\x45\x44IT_FAILURE_NOT_NAMED\x10\x07\x12\"\n\x1e\x45\x44IT_FAILURE_RENAME_REFERENCED\x10\x08\x12\"\n\x1e\x45\x44IT_FAILURE_OVERLAPPING_EDITS\x10\t\x12\x1f\n\x1b\x45\x44IT_FAILURE_RESULT_INVALID\x10\n\x12\x1e\n\x1a\x45\x44IT_FAILURE_OWNER_UNKNOWN\x10\x0b\x12$\n EDIT_FAILURE_OWNER_NOT_NAMESPACE\x10\x0c\x12\x1d\n\x19\x45\x44IT_FAILURE_ILLEGAL_KIND\x10\r\x12\"\n\x1e\x45\x44IT_FAILURE_MEMBER_NAME_TAKEN\x10\x0e\x12\"\n\x1e\x45\x44IT_FAILURE_DELETE_REFERENCED\x10\x0f*\x92\x01\n\x11PrimitiveOperator\x12\"\n\x1ePRIMITIVE_OPERATOR_UNSPECIFIED\x10\x00\x12\x1c\n\x18PRIMITIVE_OPERATOR_EQUAL\x10\x01\x12\x1e\n\x1aPRIMITIVE_OPERATOR_GREATER\x10\x02\x12\x1b\n\x17PRIMITIVE_OPERATOR_LESS\x10\x03*n\n\x11\x43ompositeOperator\x12\"\n\x1e\x43OMPOSITE_OPERATOR_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x43OMPOSITE_OPERATOR_AND\x10\x01\x12\x19\n\x15\x43OMPOSITE_OPERATOR_OR\x10\x02\x32\xa4\x0b\n\x0cSysMLService\x12\x44\n\rGetServerInfo\x12\x18.sysml.ServerInfoRequest\x1a\x19.sysml.ServerInfoResponse\x12>\n\tParseFile\x12\x17.sysml.ParseFileRequest\x1a\x18.sysml.ParseFileResponse\x12G\n\x0cParseSources\x12\x1a.sysml.ParseSourcesRequest\x1a\x1b.sysml.ParseSourcesResponse\x12;\n\tGetSymbol\x12\x17.sysml.GetSymbolRequest\x1a\x15.sysml.SymbolResponse\x12G\n\x0eGetDiagnostics\x12\x19.sysml.DiagnosticsRequest\x1a\x1a.sysml.DiagnosticsResponse\x12;\n\x08\x45valuate\x12\x16.sysml.EvaluateRequest\x1a\x17.sysml.EvaluateResponse\x12\x44\n\x0bInstantiate\x12\x19.sysml.InstantiateRequest\x1a\x1a.sysml.InstantiateResponse\x12J\n\rExecuteAction\x12\x1b.sysml.ExecuteActionRequest\x1a\x1c.sysml.ExecuteActionResponse\x12G\n\x0c\x45xecuteState\x12\x1a.sysml.ExecuteStateRequest\x1a\x1b.sysml.ExecuteStateResponse\x12\x38\n\x07\x43onvert\x12\x15.sysml.ConvertRequest\x1a\x16.sysml.ConvertResponse\x12\x41\n\nApplyEdits\x12\x18.sysml.ApplyEditsRequest\x1a\x19.sysml.ApplyEditsResponse\x12S\n\x10VerifyConstraint\x12\x1e.sysml.VerifyConstraintRequest\x1a\x1f.sysml.VerifyConstraintResponse\x12V\n\x11VerifyRequirement\x12\x1f.sysml.VerifyRequirementRequest\x1a .sysml.VerifyRequirementResponse\x12Y\n\x12VerifySatisfaction\x12 .sysml.VerifySatisfactionRequest\x1a!.sysml.VerifySatisfactionResponse\x12G\n\x0c\x45valuateCalc\x12\x1a.sysml.EvaluateCalcRequest\x1a\x1b.sysml.EvaluateCalcResponse\x12\x44\n\x0bRunAnalysis\x12\x19.sysml.RunAnalysisRequest\x1a\x1a.sysml.RunAnalysisResponse\x12;\n\x08RunSweep\x12\x16.sysml.RunSweepRequest\x1a\x17.sysml.RunSweepResponse\x12\x32\n\x05Query\x12\x13.sysml.QueryRequest\x1a\x14.sysml.QueryResponse\x12S\n\x10RunDocumentQuery\x12\x1e.sysml.RunDocumentQueryRequest\x1a\x1f.sysml.RunDocumentQueryResponse\x12M\n\x0eRenderDocument\x12\x1c.sysml.RenderDocumentRequest\x1a\x1d.sysml.RenderDocumentResponseB*Z(github.com/Open-MBEE/OpenSysML/api/protob\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -50,14 +50,14 @@ _globals['_QUERYRESULTELEMENT_PROPERTIESENTRY']._serialized_options = b'8\001' _globals['_RUNSWEEPREQUEST_NAMEDARGUMENTSENTRY']._loaded_options = None _globals['_RUNSWEEPREQUEST_NAMEDARGUMENTSENTRY']._serialized_options = b'8\001' - _globals['_FAILUREREASON']._serialized_start=10411 - _globals['_FAILUREREASON']._serialized_end=10558 - _globals['_EDITFAILURE']._serialized_start=10561 - _globals['_EDITFAILURE']._serialized_end=11102 - _globals['_PRIMITIVEOPERATOR']._serialized_start=11105 - _globals['_PRIMITIVEOPERATOR']._serialized_end=11251 - _globals['_COMPOSITEOPERATOR']._serialized_start=11253 - _globals['_COMPOSITEOPERATOR']._serialized_end=11363 + _globals['_FAILUREREASON']._serialized_start=10425 + _globals['_FAILUREREASON']._serialized_end=10572 + _globals['_EDITFAILURE']._serialized_start=10575 + _globals['_EDITFAILURE']._serialized_end=11116 + _globals['_PRIMITIVEOPERATOR']._serialized_start=11119 + _globals['_PRIMITIVEOPERATOR']._serialized_end=11265 + _globals['_COMPOSITEOPERATOR']._serialized_start=11267 + _globals['_COMPOSITEOPERATOR']._serialized_end=11377 _globals['_VERDICT']._serialized_start=23 _globals['_VERDICT']._serialized_end=249 _globals['_VERIFYCONSTRAINTREQUEST']._serialized_start=251 @@ -189,57 +189,57 @@ _globals['_UNITFACTOR']._serialized_start=7664 _globals['_UNITFACTOR']._serialized_end=7711 _globals['_DIAGNOSTIC']._serialized_start=7713 - _globals['_DIAGNOSTIC']._serialized_end=7787 - _globals['_SPAN']._serialized_start=7789 - _globals['_SPAN']._serialized_end=7883 - _globals['_SERVERINFOREQUEST']._serialized_start=7885 - _globals['_SERVERINFOREQUEST']._serialized_end=7904 - _globals['_SERVERINFORESPONSE']._serialized_start=7906 - _globals['_SERVERINFORESPONSE']._serialized_end=7965 - _globals['_QUERYREQUEST']._serialized_start=7967 - _globals['_QUERYREQUEST']._serialized_end=8050 - _globals['_QUERYRESPONSE']._serialized_start=8052 - _globals['_QUERYRESPONSE']._serialized_end=8112 - _globals['_QUERY']._serialized_start=8114 - _globals['_QUERY']._serialized_end=8186 - _globals['_CONSTRAINT']._serialized_start=8188 - _globals['_CONSTRAINT']._serialized_end=8312 - _globals['_PRIMITIVECONSTRAINT']._serialized_start=8314 - _globals['_PRIMITIVECONSTRAINT']._serialized_end=8429 - _globals['_COMPOSITECONSTRAINT']._serialized_start=8431 - _globals['_COMPOSITECONSTRAINT']._serialized_end=8535 - _globals['_QUERYRESULTELEMENT']._serialized_start=8538 - _globals['_QUERYRESULTELEMENT']._serialized_end=8698 - _globals['_QUERYRESULTELEMENT_PROPERTIESENTRY']._serialized_start=8649 - _globals['_QUERYRESULTELEMENT_PROPERTIESENTRY']._serialized_end=8698 - _globals['_SWEEPRANGE']._serialized_start=8700 - _globals['_SWEEPRANGE']._serialized_end=8815 - _globals['_RUNSWEEPREQUEST']._serialized_start=8818 - _globals['_RUNSWEEPREQUEST']._serialized_end=9138 + _globals['_DIAGNOSTIC']._serialized_end=7801 + _globals['_SPAN']._serialized_start=7803 + _globals['_SPAN']._serialized_end=7897 + _globals['_SERVERINFOREQUEST']._serialized_start=7899 + _globals['_SERVERINFOREQUEST']._serialized_end=7918 + _globals['_SERVERINFORESPONSE']._serialized_start=7920 + _globals['_SERVERINFORESPONSE']._serialized_end=7979 + _globals['_QUERYREQUEST']._serialized_start=7981 + _globals['_QUERYREQUEST']._serialized_end=8064 + _globals['_QUERYRESPONSE']._serialized_start=8066 + _globals['_QUERYRESPONSE']._serialized_end=8126 + _globals['_QUERY']._serialized_start=8128 + _globals['_QUERY']._serialized_end=8200 + _globals['_CONSTRAINT']._serialized_start=8202 + _globals['_CONSTRAINT']._serialized_end=8326 + _globals['_PRIMITIVECONSTRAINT']._serialized_start=8328 + _globals['_PRIMITIVECONSTRAINT']._serialized_end=8443 + _globals['_COMPOSITECONSTRAINT']._serialized_start=8445 + _globals['_COMPOSITECONSTRAINT']._serialized_end=8549 + _globals['_QUERYRESULTELEMENT']._serialized_start=8552 + _globals['_QUERYRESULTELEMENT']._serialized_end=8712 + _globals['_QUERYRESULTELEMENT_PROPERTIESENTRY']._serialized_start=8663 + _globals['_QUERYRESULTELEMENT_PROPERTIESENTRY']._serialized_end=8712 + _globals['_SWEEPRANGE']._serialized_start=8714 + _globals['_SWEEPRANGE']._serialized_end=8829 + _globals['_RUNSWEEPREQUEST']._serialized_start=8832 + _globals['_RUNSWEEPREQUEST']._serialized_end=9152 _globals['_RUNSWEEPREQUEST_NAMEDARGUMENTSENTRY']._serialized_start=1782 _globals['_RUNSWEEPREQUEST_NAMEDARGUMENTSENTRY']._serialized_end=1849 - _globals['_SWEEPROW']._serialized_start=9141 - _globals['_SWEEPROW']._serialized_end=9341 - _globals['_RUNSWEEPRESPONSE']._serialized_start=9344 - _globals['_RUNSWEEPRESPONSE']._serialized_end=9581 - _globals['_RUNDOCUMENTQUERYREQUEST']._serialized_start=9583 - _globals['_RUNDOCUMENTQUERYREQUEST']._serialized_end=9693 - _globals['_DOCUMENTQUERYBINDING']._serialized_start=9695 - _globals['_DOCUMENTQUERYBINDING']._serialized_end=9774 - _globals['_DOCUMENTVALUE']._serialized_start=9777 - _globals['_DOCUMENTVALUE']._serialized_end=9990 - _globals['_DOCUMENTQUERYCOLUMN']._serialized_start=9992 - _globals['_DOCUMENTQUERYCOLUMN']._serialized_end=10027 - _globals['_DOCUMENTQUERYCELL']._serialized_start=10029 - _globals['_DOCUMENTQUERYCELL']._serialized_end=10086 - _globals['_DOCUMENTQUERYROW']._serialized_start=10088 - _globals['_DOCUMENTQUERYROW']._serialized_end=10186 - _globals['_RUNDOCUMENTQUERYRESPONSE']._serialized_start=10188 - _globals['_RUNDOCUMENTQUERYRESPONSE']._serialized_end=10298 - _globals['_RENDERDOCUMENTREQUEST']._serialized_start=10300 - _globals['_RENDERDOCUMENTREQUEST']._serialized_end=10364 - _globals['_RENDERDOCUMENTRESPONSE']._serialized_start=10366 - _globals['_RENDERDOCUMENTRESPONSE']._serialized_end=10408 - _globals['_SYSMLSERVICE']._serialized_start=11366 - _globals['_SYSMLSERVICE']._serialized_end=12810 + _globals['_SWEEPROW']._serialized_start=9155 + _globals['_SWEEPROW']._serialized_end=9355 + _globals['_RUNSWEEPRESPONSE']._serialized_start=9358 + _globals['_RUNSWEEPRESPONSE']._serialized_end=9595 + _globals['_RUNDOCUMENTQUERYREQUEST']._serialized_start=9597 + _globals['_RUNDOCUMENTQUERYREQUEST']._serialized_end=9707 + _globals['_DOCUMENTQUERYBINDING']._serialized_start=9709 + _globals['_DOCUMENTQUERYBINDING']._serialized_end=9788 + _globals['_DOCUMENTVALUE']._serialized_start=9791 + _globals['_DOCUMENTVALUE']._serialized_end=10004 + _globals['_DOCUMENTQUERYCOLUMN']._serialized_start=10006 + _globals['_DOCUMENTQUERYCOLUMN']._serialized_end=10041 + _globals['_DOCUMENTQUERYCELL']._serialized_start=10043 + _globals['_DOCUMENTQUERYCELL']._serialized_end=10100 + _globals['_DOCUMENTQUERYROW']._serialized_start=10102 + _globals['_DOCUMENTQUERYROW']._serialized_end=10200 + _globals['_RUNDOCUMENTQUERYRESPONSE']._serialized_start=10202 + _globals['_RUNDOCUMENTQUERYRESPONSE']._serialized_end=10312 + _globals['_RENDERDOCUMENTREQUEST']._serialized_start=10314 + _globals['_RENDERDOCUMENTREQUEST']._serialized_end=10378 + _globals['_RENDERDOCUMENTRESPONSE']._serialized_start=10380 + _globals['_RENDERDOCUMENTRESPONSE']._serialized_end=10422 + _globals['_SYSMLSERVICE']._serialized_start=11380 + _globals['_SYSMLSERVICE']._serialized_end=12824 # @@protoc_insertion_point(module_scope) diff --git a/clients/python/opensysml/proto/sysml_pb2.pyi b/clients/python/opensysml/proto/sysml_pb2.pyi index a282991ae..84d3e21c1 100644 --- a/clients/python/opensysml/proto/sysml_pb2.pyi +++ b/clients/python/opensysml/proto/sysml_pb2.pyi @@ -816,14 +816,16 @@ class UnitFactor(_message.Message): def __init__(self, unit_id: _Optional[str] = ..., exponent: _Optional[float] = ...) -> None: ... class Diagnostic(_message.Message): - __slots__ = ("severity", "message", "span") + __slots__ = ("severity", "message", "span", "code") SEVERITY_FIELD_NUMBER: _ClassVar[int] MESSAGE_FIELD_NUMBER: _ClassVar[int] SPAN_FIELD_NUMBER: _ClassVar[int] + CODE_FIELD_NUMBER: _ClassVar[int] severity: str message: str span: Span - def __init__(self, severity: _Optional[str] = ..., message: _Optional[str] = ..., span: _Optional[_Union[Span, _Mapping]] = ...) -> None: ... + code: str + def __init__(self, severity: _Optional[str] = ..., message: _Optional[str] = ..., span: _Optional[_Union[Span, _Mapping]] = ..., code: _Optional[str] = ...) -> None: ... class Span(_message.Message): __slots__ = ("file", "start_line", "start_col", "end_line", "end_col") diff --git a/clients/python/tests/test_diagnostic.py b/clients/python/tests/test_diagnostic.py index 2e2993a92..3835646f6 100644 --- a/clients/python/tests/test_diagnostic.py +++ b/clients/python/tests/test_diagnostic.py @@ -66,3 +66,16 @@ def test_diagnostic_span_property(): # span property returns the protobuf Span object assert diag.span == pb_span assert diag.span.file == "test.sysml" + + +def test_diagnostic_code(): + coded = Diagnostic(sysml_pb2.Diagnostic( + severity="info", + message="choice point: 2 steppable tokens", + code="choice-point", + )) + uncoded = Diagnostic(sysml_pb2.Diagnostic(severity="error", message="expected '}'")) + + assert coded.code == "choice-point" + assert "code='choice-point'" in repr(coded) + assert uncoded.code == "" diff --git a/clients/python/tests/test_runtime_integration.py b/clients/python/tests/test_runtime_integration.py index 221ab6fe2..f281338a6 100644 --- a/clients/python/tests/test_runtime_integration.py +++ b/clients/python/tests/test_runtime_integration.py @@ -212,6 +212,14 @@ def test_enum_typed_slot_and_eval_return_the_literal(self): assert self.conn.eval("D::Color::red", model.hash) == red assert self.conn.eval("D::Color::green", model.hash) != red + def test_service_reports_the_diagnostic_codes_capability(self): + """The service says it populates Diagnostic.code, and does.""" + from opensysml.capabilities import CAPABILITY_DIAGNOSTIC_CODES + + assert self.conn.server_info().has(CAPABILITY_DIAGNOSTIC_CODES) + model = self.conn.load_from_content("package P { part def W { part hub : Missing; } }") + assert "unresolved" in {d.code for d in model.diagnostics} + def test_service_reports_the_enum_values_capability(self): """The wire form is a contract, so the service says it honours it.""" from opensysml.capabilities import CAPABILITY_ENUM_VALUES diff --git a/clients/rust/conformance/sysml.descriptor.binpb b/clients/rust/conformance/sysml.descriptor.binpb index bf4c1e2da..607ad1cd6 100644 Binary files a/clients/rust/conformance/sysml.descriptor.binpb and b/clients/rust/conformance/sysml.descriptor.binpb differ diff --git a/clients/rust/opensysml/src/domain.rs b/clients/rust/opensysml/src/domain.rs index b1b7c5662..3049715e0 100644 --- a/clients/rust/opensysml/src/domain.rs +++ b/clients/rust/opensysml/src/domain.rs @@ -134,6 +134,9 @@ pub struct Diagnostic { pub severity: String, /// Human-readable diagnostic message. pub message: String, + /// What was found, stable across message wording: `syntax`, a validation + /// code, `choice-point` or `guard-unevaluable`; empty when the service assigned none. + pub code: String, /// Optional source location. pub span: Option, wire: wire::Diagnostic, @@ -145,6 +148,7 @@ impl From for Diagnostic { Self { severity: wire.severity.clone(), message: wire.message.clone(), + code: wire.code.clone(), span, wire, } @@ -882,6 +886,25 @@ impl Instantiation { mod tests { use super::*; + #[test] + fn a_diagnostic_carries_its_code() { + let coded = Diagnostic::from(wire::Diagnostic { + severity: "info".to_owned(), + message: "choice point: 2 steppable tokens".to_owned(), + code: "choice-point".to_owned(), + span: None, + }); + assert_eq!(coded.code, "choice-point"); + assert_eq!(coded.wire().code, "choice-point"); + + let uncoded = Diagnostic::from(wire::Diagnostic { + severity: "error".to_owned(), + message: "expected '}'".to_owned(), + ..Default::default() + }); + assert_eq!(uncoded.code, ""); + } + #[test] fn value_arms_are_decoded_without_loss() { let sequence = wire::Value { diff --git a/clients/rust/opensysml/src/proto/sysml/sysml.rs b/clients/rust/opensysml/src/proto/sysml/sysml.rs index 89cf07971..073dfcef3 100644 --- a/clients/rust/opensysml/src/proto/sysml/sysml.rs +++ b/clients/rust/opensysml/src/proto/sysml/sysml.rs @@ -1046,6 +1046,10 @@ pub struct Diagnostic { pub message: ::prost::alloc::string::String, #[prost(message, optional, tag="3")] pub span: ::core::option::Option, + /// Stable identifier to branch on instead of the message: a pass or rule code, + /// "syntax", "choice-point", "guard-unevaluable"; empty when none was assigned. + #[prost(string, tag="4")] + pub code: ::prost::alloc::string::String, } /// Span represents a source location #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] @@ -1128,6 +1132,8 @@ pub struct ServerInfoResponse { /// and answers with typed rows. /// "render_document" - the RenderDocument RPC renders a named document to /// Markdown. + /// "diagnostic_codes" - Diagnostic.code is populated, so an empty code is a + /// finding none was assigned; without it every code is empty. #[prost(string, repeated, tag="2")] pub capabilities: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, } diff --git a/cmd/conformance/pkgclient.go b/cmd/conformance/pkgclient.go index c2d9cbbfa..48a27f911 100644 --- a/cmd/conformance/pkgclient.go +++ b/cmd/conformance/pkgclient.go @@ -732,7 +732,7 @@ func symbolToProto(symbol *opensysml.Symbol) *pb.SymbolInfo { func diagnosticsToProto(diagnostics []opensysml.Diagnostic) []*pb.Diagnostic { var out []*pb.Diagnostic for _, diagnostic := range diagnostics { - converted := &pb.Diagnostic{Severity: diagnostic.Severity, Message: diagnostic.Message} + converted := &pb.Diagnostic{Severity: diagnostic.Severity, Message: diagnostic.Message, Code: diagnostic.Code} if diagnostic.Span != nil { // #nosec G115 -- line and column numbers fit in int32. converted.Span = &pb.Span{ diff --git a/docs/reference/api.md b/docs/reference/api.md index 4fbb031e7..5d537cd29 100644 --- a/docs/reference/api.md +++ b/docs/reference/api.md @@ -334,9 +334,11 @@ Higher tiers skip if lower tier fails. - `Model() *semantics.Model` - **`Diagnostic`** — Error/warning - - `Level DiagnosticLevel` — Error, Warning, Info + - `Severity Severity` — Error, Warning, Info - `Span source.Span` - `Message string` + - `Code string` — stable identifier of what was found (`syntax`, a pass or rule code, + `choice-point`, `guard-unevaluable`); carried as-is on the wire as `Diagnostic.code` **Usage:** ```go diff --git a/docs/reference/service-transports.md b/docs/reference/service-transports.md index 46a312f1b..30dc88408 100644 --- a/docs/reference/service-transports.md +++ b/docs/reference/service-transports.md @@ -52,7 +52,7 @@ capability's definition rather than something a client has to guess: | The capability describes | A request that needs it | What a client should do | |---|---|---| | what the service can be *asked*: `strict_conformance`, `inline_language`, `parse_sources`, `evaluate_subject`, `verification`, `convert`, `apply_edits`, `authoring`, `query`, `oslc_query`, `document_query`, `render_document` | is **refused** with `UNIMPLEMENTED`, naming the capability | check the advertised list first, and report the missing capability locally rather than spending a round trip | -| how a response is *populated*: `type_facts`, `symbol_attributes`, `feature_values`, `enum_values`, `unset_value`, `complex_values`, `structured_values`, `measurement_refs`, `function_values`, `verification_verdicts`, `infinity_value` | is answered with those fields **omitted** | check before reading the fields; an omitted field is not an error | +| how a response is *populated*: `type_facts`, `symbol_attributes`, `feature_values`, `enum_values`, `unset_value`, `complex_values`, `structured_values`, `measurement_refs`, `function_values`, `verification_verdicts`, `infinity_value`, `diagnostic_codes` | is answered with those fields **omitted** | check before reading the fields; an omitted field is not an error | `complex_values`, `structured_values`, `measurement_refs`, `function_values` and `infinity_value` sit in both rows: a complex — or an array, vector or vector quantity, a bare measurement reference, a calc held as a diff --git a/docs/reference/wire-contract.md b/docs/reference/wire-contract.md index 37fe8646d..306ae2ccf 100644 --- a/docs/reference/wire-contract.md +++ b/docs/reference/wire-contract.md @@ -65,7 +65,7 @@ same mapping, and three of its rules matter here: ```console $ … /Evaluate -d '{"modelHash":"2af52c50cee63699ece8f9021b6344e4fe9f2fe6eeb0f3f8edd9feaa5443dea2","expresion":"1 + 1"}' -{"error":"expression parse failed","diagnostics":[{"severity":"error","message":"expected an expression","span":{"file":"","startLine":1,"startCol":1,"endLine":1,"endCol":1}}]} +{"error":"expression parse failed","diagnostics":[{"severity":"error","message":"expected an expression","span":{"file":"","startLine":1,"startCol":1,"endLine":1,"endCol":1},"code":"syntax"}]} ``` A body that is not valid JSON, by contrast, is refused with a Connect error (see @@ -115,7 +115,7 @@ check `diagnostics` for `"severity":"error"` first: ```console $ … /ParseSources -d '{"documents":[{"name":"syntax_error.sysml","content":"package Test { invalid syntax ((( }\n"}]}' -{"modelHash":"da0e2628154910330555183af59d8f803233352122b69f64da8ff138094f0c50","roots":[{"kind":"RootNamespace","childIds":["Test"]}],"diagnostics":[{"severity":"error","message":"expected a namespace member","span":{"file":"syntax_error.sysml","startLine":1,"startCol":16,"endLine":1,"endCol":23}}]} +{"modelHash":"da0e2628154910330555183af59d8f803233352122b69f64da8ff138094f0c50","roots":[{"kind":"RootNamespace","childIds":["Test"]}],"diagnostics":[{"severity":"error","message":"expected a namespace member","span":{"file":"syntax_error.sysml","startLine":1,"startCol":16,"endLine":1,"endCol":23},"code":"syntax"}]} ``` What *is* refused, with a Connect error, is a request the service cannot make a model from at @@ -545,13 +545,31 @@ type-check, an action has no start, a value overflowed. ### Diagnostics: the shape of a finding ```json -{"severity":"error","message":"expected a namespace member","span":{"file":"syntax_error.sysml","startLine":1,"startCol":16,"endLine":1,"endCol":23}} +{"severity":"error","message":"expected a namespace member","span":{"file":"syntax_error.sysml","startLine":1,"startCol":16,"endLine":1,"endCol":23},"code":"syntax"} ``` -`severity` is `"error"`, `"warning"` or `"info"`. `span` locates it: `file` is the document's -`name` from the request (or `` for an `Evaluate` expression), lines and columns are -**1-based**, `end*` is exclusive, and the whole `span` is omitted when there is no location. -Line and column are `int32`, so unlike `int64` they are JSON *numbers*. +| Field | Type | Meaning | +|---|---|---| +| `severity` | string | `"error"`, `"warning"` or `"info"` | +| `message` | string | The finding, worded for a person; may change between releases | +| `span` | `Span` | Where it is; omitted when there is no location | +| `code` | string | What it is, stable across wording; `""` when the producer assigned none | + +`span` locates it: `file` is the document's `name` from the request (or `` for an +`Evaluate` expression), lines and columns are **1-based**, `end*` is exclusive, and the whole +`span` is omitted when there is no location. Line and column are `int32`, so unlike `int64` +they are JSON *numbers*. + +`code` is the identifier to branch on; `message` is not. A syntax error is `"syntax"`, whether +it came from a document, an `Evaluate` expression, an edit's new value or a `Convert` input. A +validation finding carries its pass or rule code, the same one the LSP reports as the +diagnostic's code (`"unresolved"` for a name that resolves to nothing, for instance). A run's +notes are `"choice-point"` and `"guard-unevaluable"` (see [`ExecuteAction`](#executeaction)). +The field is a proto3 string, so a producer that assigns no code sends `""`, which the JSON +encoding omits; treat a missing `code` as empty, never as an error. A service that populates +the field advertises the `diagnostic_codes` capability; from one that does not, every `code` is +empty and says nothing about the finding, so check the capability before branching on it. New +codes may appear in a release; a code, once published, keeps its meaning. ### In-body failures @@ -776,7 +794,7 @@ done; … }` with a succession from `split` to each branch and from each to `syn ```console $ … /ExecuteAction -d '{"modelHash":"81b1…73fc","actionSymbolId":"Test::tally"}' -{"outputs":{"leftCount":{"intValue":"1"},"rightCount":{"intValue":"10"}},"diagnostics":[{"severity":"info","message":"choice point: step 3: tokens 2@left, 3@right (unordered; took 3@right first)","span":{"file":"tally.sysml","startLine":2,"startCol":2,"endLine":20,"endCol":2}}]} +{"outputs":{"leftCount":{"intValue":"1"},"rightCount":{"intValue":"10"}},"diagnostics":[{"severity":"info","message":"choice point: step 3: tokens 2@left, 3@right (unordered; took 3@right first)","span":{"file":"tally.sysml","startLine":2,"startCol":2,"endLine":20,"endCol":2},"code":"choice-point"}]} ``` A run with no `diagnostics` had exactly one order to take. The order taken is the engine's fixed @@ -793,12 +811,14 @@ then warn; if 1 / (level - 75) > 0 then alarm; … }`): ```console $ … /ExecuteAction -d '{"modelHash":"81b1…73fc","actionSymbolId":"Test::route"}' -{"outputs":{"level":{"intValue":"75"},"handler":{"intValue":"1"}},"diagnostics":[{"severity":"info","message":"guard not evaluable: step 2: decision select branch 2->alarm: division by zero (not selected)","span":{"file":"tally.sysml","startLine":31,"startCol":10,"endLine":31,"endCol":30}}]} +{"outputs":{"level":{"intValue":"75"},"handler":{"intValue":"1"}},"diagnostics":[{"severity":"info","message":"guard not evaluable: step 2: decision select branch 2->alarm: division by zero (not selected)","span":{"file":"tally.sysml","startLine":31,"startCol":10,"endLine":31,"endCol":30},"code":"guard-unevaluable"}]} ``` The first guard read is the run's own, not a preview: when it cannot be evaluated the run fails with `error` as it always has, and no `guard not evaluable` diagnostic is added. The two kinds are -told apart by message prefix, `choice point: ` and `guard not evaluable: `; both are `"info"`. +told apart by `code`, `"choice-point"` and `"guard-unevaluable"`; both are `"info"`, and the +message prefixes `choice point: ` and `guard not evaluable: ` are for reading, not branching. +`RunAnalysis` carries the same two codes for the runs it makes. ### `ExecuteState` @@ -839,7 +859,7 @@ Idle accept Go then B; }` in the same document: ```console $ … /ExecuteState -d '{"modelHash":"81b1…73fc","stateMachineSymbolId":"Test::Hub","events":["Go"]}' -{"statesVisited":["Idle","A"],"diagnostics":[{"severity":"info","message":"choice point: state Idle on accept Go: transitions 1->A, 2->B (unordered; took 1->A)","span":{"file":"tally.sysml","startLine":25,"startCol":3,"endLine":26,"endCol":3}}]} +{"statesVisited":["Idle","A"],"diagnostics":[{"severity":"info","message":"choice point: state Idle on accept Go: transitions 1->A, 2->B (unordered; took 1->A)","span":{"file":"tally.sysml","startLine":25,"startCol":3,"endLine":26,"endCol":3},"code":"choice-point"}]} ``` ### `EvaluateCalc` diff --git a/internal/core/edit/validate.go b/internal/core/edit/validate.go index 8dd3dd991..dcae14de0 100644 --- a/internal/core/edit/validate.go +++ b/internal/core/edit/validate.go @@ -138,7 +138,7 @@ func parseDiagnostics(diags []parser.Diagnostic) []passes.Diagnostic { Severity: passes.SeverityError, Span: d.Span, Message: d.Message, - Code: d.Code, + Code: "syntax", Source: "syntax", }) } diff --git a/internal/grpc/analysis.go b/internal/grpc/analysis.go index de57c4545..4dd7857d9 100644 --- a/internal/grpc/analysis.go +++ b/internal/grpc/analysis.go @@ -70,7 +70,7 @@ func (s *Service) RunAnalysis(ctx context.Context, req *pb.RunAnalysisRequest) ( return &pb.RunAnalysisResponse{ Error: fmt.Sprintf("verification run failed: %v", verr), FailureReason: failureReason(verr), - Diagnostics: RunNoteDiagnosticsToProto(v.runtime.Notes(), v.cached), + Diagnostics: v.service.filterDiagnosticCapabilities(RunNoteDiagnosticsToProto(v.runtime.Notes(), v.cached)), }, nil } result = verified.Run @@ -79,10 +79,10 @@ func (s *Service) RunAnalysis(ctx context.Context, req *pb.RunAnalysisRequest) ( return &pb.RunAnalysisResponse{ Error: fmt.Sprintf("analysis run failed: %v", err), FailureReason: failureReason(err), - Diagnostics: RunNoteDiagnosticsToProto(v.runtime.Notes(), v.cached), + Diagnostics: v.service.filterDiagnosticCapabilities(RunNoteDiagnosticsToProto(v.runtime.Notes(), v.cached)), }, nil } - diags := RunNoteDiagnosticsToProto(v.runtime.Notes(), v.cached) + diags := v.service.filterDiagnosticCapabilities(RunNoteDiagnosticsToProto(v.runtime.Notes(), v.cached)) // The case reports the subject it ran on: the one supplied, or the one the // usage or the enclosing case bound. subject = result.Subject diff --git a/internal/grpc/capability_response.go b/internal/grpc/capability_response.go index de9a0f0ab..dab040a50 100644 --- a/internal/grpc/capability_response.go +++ b/internal/grpc/capability_response.go @@ -58,6 +58,15 @@ func (s *Service) filterInstanceCapabilities(instance *pb.Instance) { } } +func (s *Service) filterDiagnosticCapabilities(diags []*pb.Diagnostic) []*pb.Diagnostic { + if !s.capabilities.has(CapabilityDiagnosticCodes) { + for _, diag := range diags { + diag.Code = "" + } + } + return diags +} + func (s *Service) filterValueCapabilities(value *pb.Value) { if value == nil { return diff --git a/internal/grpc/convert.go b/internal/grpc/convert.go index 62f3ee888..c9c5ee757 100644 --- a/internal/grpc/convert.go +++ b/internal/grpc/convert.go @@ -83,6 +83,7 @@ func DiagnosticToProto(diag passes.Diagnostic, sf *source.SourceFile) *pb.Diagno return &pb.Diagnostic{ Severity: diag.Severity.String(), Message: diag.Message, + Code: diag.Code, Span: &pb.Span{ File: sf.Name(), StartLine: int32Clamp(start.Line), @@ -108,12 +109,16 @@ func RunNoteDiagnosticsToProto(notes []runtime.RunNote, model *CachedModel) []*p pbDiags = append(pbDiags, DiagnosticToProto(diag, sf)) continue } - pbDiags = append(pbDiags, &pb.Diagnostic{Severity: diag.Severity.String(), Message: diag.Message}) + pbDiags = append(pbDiags, &pb.Diagnostic{Severity: diag.Severity.String(), Message: diag.Message, Code: diag.Code}) } return pbDiags } -// ParserDiagnosticToProto converts a parser.Diagnostic to protobuf. +// SyntaxDiagnosticCode is the code every reporter gives a parser error; the +// parser itself codes only warnings. +const SyntaxDiagnosticCode = "syntax" + +// ParserDiagnosticToProto converts a parser error to protobuf. func ParserDiagnosticToProto(diag parser.Diagnostic, sf *source.SourceFile) *pb.Diagnostic { li := sf.Lines() start := li.PosAt(diag.Span.Offset) @@ -122,6 +127,7 @@ func ParserDiagnosticToProto(diag parser.Diagnostic, sf *source.SourceFile) *pb. return &pb.Diagnostic{ Severity: "error", // Parser diagnostics are always errors Message: diag.Message, + Code: SyntaxDiagnosticCode, Span: &pb.Span{ File: sf.Name(), StartLine: int32Clamp(start.Line), diff --git a/internal/grpc/diagnostic_code_test.go b/internal/grpc/diagnostic_code_test.go new file mode 100644 index 000000000..086a4cb84 --- /dev/null +++ b/internal/grpc/diagnostic_code_test.go @@ -0,0 +1,443 @@ +package grpc + +import ( + "context" + "strings" + "testing" + + pb "github.com/Open-MBEE/OpenSysML/api/proto" + "github.com/Open-MBEE/OpenSysML/internal/core/runtime" + "google.golang.org/protobuf/proto" +) + +// codesOf lists the codes of diags, in order. +func codesOf(diags []*pb.Diagnostic) []string { + out := make([]string, 0, len(diags)) + for _, d := range diags { + out = append(out, d.Code) + } + return out +} + +// requireCode fails unless some diagnostic carries code, and every diagnostic +// carrying it is what its message says it is. +func requireCode(t *testing.T, diags []*pb.Diagnostic, code, messagePrefix string) { + t.Helper() + found := false + for _, d := range diags { + if d.Code != code { + continue + } + found = true + if !strings.HasPrefix(d.Message, messagePrefix) { + t.Errorf("code %q on %q, want a message starting %q", code, d.Message, messagePrefix) + } + } + if !found { + t.Errorf("no diagnostic coded %q among %v", code, codesOf(diags)) + } +} + +// requireEveryCoded fails when any diagnostic crosses without a code. +func requireEveryCoded(t *testing.T, diags []*pb.Diagnostic) { + t.Helper() + for _, d := range diags { + if d.Code == "" { + t.Errorf("diagnostic crossed uncoded: %s %q", d.Severity, d.Message) + } + } +} + +const codedModel = ` +package Coded { + part def Wheel { + part hub : Missing; + } +} +` + +// A parse reports a syntax error as "syntax" and a validation finding under the +// code its pass gave it, and GetDiagnostics reports the same codes. +func TestParseFile_DiagnosticCodes(t *testing.T) { + srv := mustNewService(t, 10) + + parseResp, err := srv.ParseFile(context.Background(), &pb.ParseFileRequest{ + Source: &pb.ParseFileRequest_Content{Content: codedModel}, + }) + if err != nil { + t.Fatalf("ParseFile: %v", err) + } + requireCode(t, parseResp.Diagnostics, "unresolved", "unresolved reference") + requireEveryCoded(t, parseResp.Diagnostics) + + diagResp, err := srv.GetDiagnostics(context.Background(), &pb.DiagnosticsRequest{ModelHash: parseResp.ModelHash}) + if err != nil { + t.Fatalf("GetDiagnostics: %v", err) + } + if got, want := strings.Join(codesOf(diagResp.Diagnostics), ","), strings.Join(codesOf(parseResp.Diagnostics), ","); got != want { + t.Errorf("GetDiagnostics codes = %s, want the parse's %s", got, want) + } + + broken, err := srv.ParseFile(context.Background(), &pb.ParseFileRequest{ + Source: &pb.ParseFileRequest_Content{Content: "package P { part def "}, + }) + if err != nil { + t.Fatalf("ParseFile: %v", err) + } + if len(broken.Diagnostics) == 0 { + t.Fatal("a syntax error produced no diagnostic") + } + for _, d := range broken.Diagnostics { + if d.Code != SyntaxDiagnosticCode { + t.Errorf("syntax error coded %q, want %q: %s", d.Code, SyntaxDiagnosticCode, d.Message) + } + } +} + +// A document set's diagnostics carry their codes as one document's do: a +// validation code when the set parses, "syntax" when a document does not. +func TestParseSources_DiagnosticCodes(t *testing.T) { + srv := mustNewService(t, 10) + defer srv.Close() + + resp, err := srv.ParseSources(context.Background(), &pb.ParseSourcesRequest{ + Documents: inlineDocuments("coded.sysml", codedModel, "empty.sysml", "package Empty {}"), + }) + if err != nil { + t.Fatalf("ParseSources: %v", err) + } + requireCode(t, resp.Diagnostics, "unresolved", "unresolved reference") + requireEveryCoded(t, resp.Diagnostics) + + resp, err = srv.ParseSources(context.Background(), &pb.ParseSourcesRequest{ + Documents: inlineDocuments("coded.sysml", codedModel, "broken.sysml", "package P { part def "), + }) + if err != nil { + t.Fatalf("ParseSources: %v", err) + } + requireCode(t, resp.Diagnostics, SyntaxDiagnosticCode, "") + requireEveryCoded(t, resp.Diagnostics) +} + +// An expression that does not parse is refused with "syntax" diagnostics. +func TestEvaluate_DiagnosticCodes(t *testing.T) { + srv := mustNewService(t, 10) + hash := mustParse(t, srv, "package P {}") + + resp, err := srv.Evaluate(context.Background(), &pb.EvaluateRequest{ModelHash: hash, Expression: "1 +"}) + if err != nil { + t.Fatalf("Evaluate: %v", err) + } + if resp.Error == "" || len(resp.Diagnostics) == 0 { + t.Fatalf("an unparsable expression evaluated: %v", resp) + } + for _, d := range resp.Diagnostics { + if d.Code != SyntaxDiagnosticCode { + t.Errorf("syntax error coded %q, want %q: %s", d.Code, SyntaxDiagnosticCode, d.Message) + } + } +} + +// An action run reports its choice points as "choice-point" and the guards it +// could not evaluate as "guard-unevaluable", whether or not the choice was +// located in the model. +func TestExecuteAction_DiagnosticCodes(t *testing.T) { + srv := mustNewService(t, 10) + + content := ` +package Test { + action tally { + attribute leftCount : Integer = 0; + attribute rightCount : Integer = 0; + first start; + fork split; + action left { assign leftCount := leftCount + 1; } + action right { assign rightCount := rightCount + 10; } + join sync; + done; + succession first start then split; + succession first split then left; + succession first split then right; + succession first left then sync; + succession first right then sync; + succession first sync then done; + } + action route { + attribute level : Integer = 75; + attribute handler : Integer = 0; + first start; + then decide select; + if level > 50 then warn; + if 1 / (level - 75) > 0 then alarm; + action warn { assign handler := 1; } + then done; + action alarm { assign handler := 2; } + then done; + } +} +` + hash := mustParse(t, srv, content) + + resp, err := srv.ExecuteAction(context.Background(), &pb.ExecuteActionRequest{ModelHash: hash, ActionSymbolId: "Test::tally"}) + if err != nil { + t.Fatalf("ExecuteAction: %v", err) + } + if resp.Error != "" { + t.Fatalf("execution error: %s", resp.Error) + } + requireCode(t, resp.Diagnostics, runtime.ChoiceDiagnosticCode, "choice point: ") + requireEveryCoded(t, resp.Diagnostics) + + resp, err = srv.ExecuteAction(context.Background(), &pb.ExecuteActionRequest{ModelHash: hash, ActionSymbolId: "Test::route"}) + if err != nil { + t.Fatalf("ExecuteAction: %v", err) + } + if resp.Error != "" { + t.Fatalf("execution error: %s", resp.Error) + } + requireCode(t, resp.Diagnostics, runtime.UnevaluableGuardCode, "guard not evaluable: ") + requireEveryCoded(t, resp.Diagnostics) +} + +// A state run's choice among transitions is coded "choice-point". +func TestExecuteState_DiagnosticCodes(t *testing.T) { + srv := mustNewService(t, 10) + hash := mustParse(t, srv, ` +package Test { + state Dispatcher { + attribute level : Integer = 8; + entry; then idle; + state idle; + state low; + state high; + transition first idle accept Go if level > 5 then low; + transition first idle accept Go if level > 7 then high; + } +} +`) + + resp, err := srv.ExecuteState(context.Background(), &pb.ExecuteStateRequest{ + ModelHash: hash, StateMachineSymbolId: "Test::Dispatcher", Events: []string{"Go"}, + }) + if err != nil { + t.Fatalf("ExecuteState: %v", err) + } + if resp.Error != "" { + t.Fatalf("execution error: %s", resp.Error) + } + requireCode(t, resp.Diagnostics, runtime.ChoiceDiagnosticCode, "choice point: ") + requireEveryCoded(t, resp.Diagnostics) +} + +// An analysis run's choice points, among tokens and among writes, are coded +// "choice-point". +func TestRunAnalysis_DiagnosticCodes(t *testing.T) { + srv := mustNewService(t, 10) + hash := mustVerifyModel(t, srv, ` +package An { + private import ScalarValues::*; + + action def Tally { + out r : Integer = 0; + first start; + fork split; + action left { assign r := r + 1; } + action right { assign r := r + 10; } + join sync; + done; + succession first start then split; + succession first split then left; + succession first split then right; + succession first left then sync; + succession first right then sync; + succession first sync then done; + } + + analysis forked { + out r : Integer; + perform action tally : Tally; + return : Integer = r; + } +} +`, "analysis-choice-codes") + + resp := runAnalysis(t, srv, &pb.RunAnalysisRequest{ModelHash: hash, SymbolId: "An::forked"}) + if resp.Error != "" { + t.Fatalf("RunAnalysis reported %q", resp.Error) + } + if len(resp.Diagnostics) != 2 { + t.Fatalf("diagnostics = %v, want the two choice points", resp.Diagnostics) + } + requireCode(t, resp.Diagnostics, runtime.ChoiceDiagnosticCode, "choice point: ") + requireEveryCoded(t, resp.Diagnostics) +} + +// A conversion refused for a syntax error codes each diagnostic "syntax", +// with a span and without one alike. +func TestConvert_DiagnosticCodes(t *testing.T) { + srv := mustNewService(t, 10) + + for name, req := range map[string]*pb.ConvertRequest{ + "notation": { + Source: &pb.ConvertRequest_Content{Content: "package P { part def "}, + FromFormat: "sysml", + ToFormat: "ttl", + }, + "turtle": { + Source: &pb.ConvertRequest_Content{Content: "@prefix : .\n:a :b"}, + FromFormat: "ttl", + ToFormat: "sysml", + }, + } { + resp, err := srv.Convert(context.Background(), req) + if err != nil { + t.Fatalf("%s: Convert: %v", name, err) + } + if resp.Error == "" || len(resp.Diagnostics) == 0 { + t.Fatalf("%s: unreadable input converted without diagnostics: %v", name, resp) + } + for _, d := range resp.Diagnostics { + if d.Code != SyntaxDiagnosticCode { + t.Errorf("%s: syntax error coded %q, want %q: %s", name, d.Code, SyntaxDiagnosticCode, d.Message) + } + } + } +} + +// An edit refused for what it would make of the model reports the diagnostics +// that refused it with their codes. +func TestApplyEdits_DiagnosticCodes(t *testing.T) { + srv := mustNewService(t, 10) + hash := mustParsedModel(t, srv, editModelSource) + + for _, tc := range []struct { + name string + value string + code string + }{ + {"value does not parse", "1050.0[", SyntaxDiagnosticCode}, + {"value does not resolve", "nosuchFeature", "unresolved"}, + } { + t.Run(tc.name, func(t *testing.T) { + resp, err := srv.ApplyEdits(context.Background(), &pb.ApplyEditsRequest{ + ModelHash: hash, + Operations: []*pb.EditOperation{setValueOp("Demo::SC::unitMass", tc.value)}, + }) + if err != nil { + t.Fatalf("ApplyEdits: %v", err) + } + if resp.Error == "" || len(resp.Diagnostics) == 0 { + t.Fatalf("refusal carries no diagnostics: %v", resp) + } + requireCode(t, resp.Diagnostics, tc.code, "") + requireEveryCoded(t, resp.Diagnostics) + }) + } +} + +// Without "diagnostic_codes" every response family still reports its +// diagnostics, identical but for the code, which is withheld; with it every +// code is populated, so an empty one is a finding none was assigned. +func TestDiagnosticCodes_Capability(t *testing.T) { + ctx := context.Background() + current := mustNewService(t, 10) + withheld := mustNewServiceWithout(t, CapabilityDiagnosticCodes) + + stateMachine := ` +package Test { + state Dispatcher { + attribute level : Integer = 8; + entry; then idle; + state idle; + state low; + state high; + transition first idle accept Go if level > 5 then low; + transition first idle accept Go if level > 7 then high; + } +} +` + families := map[string]func(srv *Service) []*pb.Diagnostic{ + "ParseFile": func(srv *Service) []*pb.Diagnostic { + resp, err := srv.ParseFile(ctx, &pb.ParseFileRequest{Source: &pb.ParseFileRequest_Content{Content: codedModel}}) + if err != nil { + t.Fatalf("ParseFile: %v", err) + } + return resp.Diagnostics + }, + "GetDiagnostics": func(srv *Service) []*pb.Diagnostic { + resp, err := srv.GetDiagnostics(ctx, &pb.DiagnosticsRequest{ModelHash: mustParse(t, srv, codedModel)}) + if err != nil { + t.Fatalf("GetDiagnostics: %v", err) + } + return resp.Diagnostics + }, + "ParseSources": func(srv *Service) []*pb.Diagnostic { + resp, err := srv.ParseSources(ctx, &pb.ParseSourcesRequest{ + Documents: inlineDocuments("coded.sysml", codedModel, "broken.sysml", "package P { part def "), + }) + if err != nil { + t.Fatalf("ParseSources: %v", err) + } + return resp.Diagnostics + }, + "Evaluate": func(srv *Service) []*pb.Diagnostic { + resp, err := srv.Evaluate(ctx, &pb.EvaluateRequest{ModelHash: mustParse(t, srv, "package P {}"), Expression: "1 +"}) + if err != nil { + t.Fatalf("Evaluate: %v", err) + } + return resp.Diagnostics + }, + "ExecuteState": func(srv *Service) []*pb.Diagnostic { + resp, err := srv.ExecuteState(ctx, &pb.ExecuteStateRequest{ + ModelHash: mustParse(t, srv, stateMachine), StateMachineSymbolId: "Test::Dispatcher", Events: []string{"Go"}, + }) + if err != nil { + t.Fatalf("ExecuteState: %v", err) + } + return resp.Diagnostics + }, + "Convert": func(srv *Service) []*pb.Diagnostic { + resp, err := srv.Convert(ctx, &pb.ConvertRequest{ + Source: &pb.ConvertRequest_Content{Content: "package P { part def "}, FromFormat: "sysml", ToFormat: "ttl", + }) + if err != nil { + t.Fatalf("Convert: %v", err) + } + return resp.Diagnostics + }, + "ApplyEdits": func(srv *Service) []*pb.Diagnostic { + resp, err := srv.ApplyEdits(ctx, &pb.ApplyEditsRequest{ + ModelHash: mustParsedModel(t, srv, editModelSource), + Operations: []*pb.EditOperation{setValueOp("Demo::SC::unitMass", "nosuchFeature")}, + }) + if err != nil { + t.Fatalf("ApplyEdits: %v", err) + } + return resp.Diagnostics + }, + } + + for name, call := range families { + t.Run(name, func(t *testing.T) { + coded := call(current) + uncoded := call(withheld) + if len(coded) == 0 { + t.Fatal("no diagnostics to compare") + } + requireEveryCoded(t, coded) + if len(uncoded) != len(coded) { + t.Fatalf("withheld service reported %d diagnostics, want %d", len(uncoded), len(coded)) + } + for i, d := range uncoded { + if d.Code != "" { + t.Errorf("withheld service reported code %q", d.Code) + } + want := proto.Clone(coded[i]).(*pb.Diagnostic) + want.Code = "" + if !proto.Equal(d, want) { + t.Errorf("withheld diagnostic = %v, want %v", d, want) + } + } + }) + } +} diff --git a/internal/grpc/edit.go b/internal/grpc/edit.go index 2756a0792..df8b1145b 100644 --- a/internal/grpc/edit.go +++ b/internal/grpc/edit.go @@ -61,7 +61,7 @@ func (s *Service) ApplyEdits(ctx context.Context, req *pb.ApplyEditsRequest) (*p } result, err := edit.Apply(model, ops) if err != nil { - return editRefusal(err, doc.Source) + return s.editRefusal(err, doc.Source) } return &pb.ApplyEditsResponse{ Content: string(result.Content), @@ -111,7 +111,7 @@ func editOperations(pbOps []*pb.EditOperation) ([]edit.Operation, error) { // editRefusal reports a refused edit as a response rather than a call failure: // the request was well formed, and the answer is why the model was not edited. -func editRefusal(err error, sf *source.SourceFile) (*pb.ApplyEditsResponse, error) { +func (s *Service) editRefusal(err error, sf *source.SourceFile) (*pb.ApplyEditsResponse, error) { var refusal *edit.Error if !errors.As(err, &refusal) { return nil, statusErrorf(connect.CodeInternal, "apply edits: %v", err) @@ -130,6 +130,7 @@ func editRefusal(err error, sf *source.SourceFile) (*pb.ApplyEditsResponse, erro for _, diag := range refusal.Diagnostics { resp.Diagnostics = append(resp.Diagnostics, DiagnosticToProto(diag, diagnosed)) } + s.filterDiagnosticCapabilities(resp.Diagnostics) return resp, nil } diff --git a/internal/grpc/export.go b/internal/grpc/export.go index 0e3c69740..9770afcca 100644 --- a/internal/grpc/export.go +++ b/internal/grpc/export.go @@ -48,12 +48,12 @@ func (s *Service) Convert(ctx context.Context, req *pb.ConvertRequest) (*pb.Conv resp.Error = err.Error() var broken *export.SyntaxError if errors.As(err, &broken) { - resp.Diagnostics = syntaxDiagnostics(broken) + resp.Diagnostics = s.filterDiagnosticCapabilities(syntaxDiagnostics(broken)) } return resp, nil } resp.Content = string(out) - resp.Diagnostics = syntaxDiagnostics(syntax) + resp.Diagnostics = s.filterDiagnosticCapabilities(syntaxDiagnostics(syntax)) return resp, nil } @@ -144,6 +144,7 @@ func syntaxDiagnostics(syntax *export.SyntaxError) []*pb.Diagnostic { diags = append(diags, &pb.Diagnostic{ Severity: "error", Message: message, + Code: SyntaxDiagnosticCode, Span: &pb.Span{File: syntax.Name}, }) } diff --git a/internal/grpc/service.go b/internal/grpc/service.go index d08827ce9..6be8062be 100644 --- a/internal/grpc/service.go +++ b/internal/grpc/service.go @@ -118,6 +118,10 @@ const CapabilityVerificationVerdicts = "verification_verdicts" // `*` as Value.infinity, rather than reporting it as an unsupported null. const CapabilityInfinityValue = "infinity_value" +// CapabilityDiagnosticCodes names the capability of populating Diagnostic.code, +// so an empty code is a finding none was assigned rather than an older service. +const CapabilityDiagnosticCodes = "diagnostic_codes" + // capabilities is what this build supports, in report order. A capability is // only ever added: renaming or dropping one breaks clients that require it. var capabilities = []string{ @@ -128,7 +132,7 @@ var capabilities = []string{ CapabilityStrictConformance, CapabilityDocumentQuery, CapabilityRenderDocument, CapabilityParseSources, CapabilityComplexValues, CapabilityStructuredValues, CapabilityMeasurementRefs, CapabilityFunctionValues, CapabilityVerificationVerdicts, - CapabilityInfinityValue, + CapabilityInfinityValue, CapabilityDiagnosticCodes, } type capabilityAvailability struct { @@ -554,7 +558,7 @@ func (s *Service) modelDiagnostics(model *CachedModel) []*pb.Diagnostic { pbDiags = append(pbDiags, DiagnosticToProto(diag, doc.Source)) } } - return pbDiags + return s.filterDiagnosticCapabilities(pbDiags) } // Evaluate evaluates a SysML expression in the context of a parsed model @@ -583,7 +587,7 @@ func (s *Service) Evaluate(ctx context.Context, req *pb.EvaluateRequest) (*pb.Ev pbDiags = append(pbDiags, ParserDiagnosticToProto(diag, exprSource)) } return &pb.EvaluateResponse{ - Diagnostics: pbDiags, + Diagnostics: s.filterDiagnosticCapabilities(pbDiags), Error: "expression parse failed", }, nil } @@ -756,7 +760,7 @@ func (s *Service) ExecuteAction(ctx context.Context, req *pb.ExecuteActionReques outputs, err := runtimeCtx.ExecuteActionWithInputs(action, inputs) // The choices the run made are reported with its outcome, failed or not: a // failure may hang on the order taken. - diags := RunNoteDiagnosticsToProto(runtimeCtx.Notes(), cached) + diags := s.filterDiagnosticCapabilities(RunNoteDiagnosticsToProto(runtimeCtx.Notes(), cached)) if err != nil { return &pb.ExecuteActionResponse{ Error: fmt.Sprintf("action execution failed: %v", err), @@ -800,7 +804,7 @@ func (s *Service) ExecuteState(ctx context.Context, req *pb.ExecuteStateRequest) // Execute state machine, injecting the requested events and capturing the // real ordered state-visit trace. finalContext, statesVisited, err := runtimeCtx.ExecuteStateWithEvents(stateMachine, req.Events) - diags := RunNoteDiagnosticsToProto(runtimeCtx.Notes(), cached) + diags := s.filterDiagnosticCapabilities(RunNoteDiagnosticsToProto(runtimeCtx.Notes(), cached)) if err != nil { return &pb.ExecuteStateResponse{ Error: fmt.Sprintf("state machine execution failed: %v", err),