From 172973d4e9ff0312c47a9cdcedf74bef91226898 Mon Sep 17 00:00:00 2001 From: "g. nicholas d'andrea" Date: Fri, 11 Apr 2025 23:09:02 -0400 Subject: [PATCH 1/3] Switch to if/then style for context properties ... to provide better error-reporting when using general-purpose JSON Schema validators. --- schemas/program/context.schema.yaml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/schemas/program/context.schema.yaml b/schemas/program/context.schema.yaml index b0dd142f5..9417f5814 100644 --- a/schemas/program/context.schema.yaml +++ b/schemas/program/context.schema.yaml @@ -8,10 +8,19 @@ description: | type: object -anyOf: - - $ref: "schema:ethdebug/format/program/context/code" - - $ref: "schema:ethdebug/format/program/context/variables" - - $ref: "schema:ethdebug/format/program/context/remark" +allOf: + - if: + required: ["code"] + then: + $ref: "schema:ethdebug/format/program/context/code" + - if: + required: ["variables"] + then: + $ref: "schema:ethdebug/format/program/context/variables" + - if: + required: ["remark"] + then: + $ref: "schema:ethdebug/format/program/context/remark" unevaluatedProperties: false From 7e18265c2d56d1029e2385706550d1243df37d59 Mon Sep 17 00:00:00 2001 From: "g. nicholas d'andrea" Date: Wed, 23 Apr 2025 20:16:01 -0400 Subject: [PATCH 2/3] Add custom rendering logic for this pattern --- .../InclusiveRequiredPropertiesSchema.tsx | 140 ++++++++++++++++++ .../schemaComposition/allOfSchema.tsx | 9 ++ 2 files changed, 149 insertions(+) create mode 100644 packages/web/src/theme/JSONSchemaViewer/JSONSchemaElements/schemaComposition/InclusiveRequiredPropertiesSchema.tsx diff --git a/packages/web/src/theme/JSONSchemaViewer/JSONSchemaElements/schemaComposition/InclusiveRequiredPropertiesSchema.tsx b/packages/web/src/theme/JSONSchemaViewer/JSONSchemaElements/schemaComposition/InclusiveRequiredPropertiesSchema.tsx new file mode 100644 index 000000000..18e037f83 --- /dev/null +++ b/packages/web/src/theme/JSONSchemaViewer/JSONSchemaElements/schemaComposition/InclusiveRequiredPropertiesSchema.tsx @@ -0,0 +1,140 @@ +import React from 'react'; +import type { JSONSchema } from "json-schema-typed/draft-2020-12" +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +import { CreateNodes } from "@theme-original/JSONSchemaViewer/components" +import { + SchemaHierarchyContextProvider, + useSchemaHierarchyContext, +} from "@theme-original/JSONSchemaViewer/contexts" + +export interface Inclusions { + propertyNames: string[]; + schemasByPropertyName: { + [propertyName: string]: { + schema: Exclude; + index: number; + } + } +} + +export interface InclusiveRequiredPropertiesSchemaProps extends Inclusions { +} + +export default function InclusiveRequiredPropertiesSchema({ + propertyNames, + schemasByPropertyName +}: InclusiveRequiredPropertiesSchemaProps): JSX.Element { + const { jsonPointer: currentJsonPointer, level: currentLevel } = + useSchemaHierarchyContext() + + return ( +
+
+ independently-inclusive required properties  + This object may specify any of the following: +
    + {propertyNames.map((propertyName, index) => +
  • {propertyName}
  • + )} +
+ + Depending on which required properties are used, the following + corresponding sub-schemas may apply: + + { + Object.entries(schemasByPropertyName) + .map(([propertyName, { schema, index }]) => ( + + + + + + )) + } + +
+ ); +} + +const isIfThen = ( + schema: JSONSchema +): schema is JSONSchema & { + if: JSONSchema; + then: JSONSchema; +} => + typeof schema !== "boolean" && + "if" in schema && "then" in schema; + +const isSingleRequiredProperty = ( + schema: JSONSchema +): schema is JSONSchema & { + required: [string] +} => + typeof schema !== "boolean" && + "required" in schema && schema.required?.length === 1; + +export function detectInclusiveRequiredProperties(schema: { + allOf: JSONSchema[] +}): Inclusions | undefined { + const { allOf } = schema; + + // every schema in the `allOf` should be structured as an if/then/else, + // where every `if` schema checks only for a single, unique required property + + if (!allOf.every(isIfThen)) { + return; + } + + const ifs = allOf.map(({ if: if_ }) => if_); + + if (!ifs.every(isSingleRequiredProperty)) { + return; + } + + const propertyNames = [...new Set( + ifs.map(({ required: [propertyName] }) => propertyName) + )]; + + // check that property names are unique + if (propertyNames.length !== ifs.length) { + console.debug("property names are not unique"); + return; + } + + + const schemasByPropertyName = ( + allOf as (JSONSchema & { if: { required: [string] }; then: Exclude; })[] + ) + .map( + ( + { + if: { required: [propertyName] }, + then + }, + index + ) => ({ + [propertyName]: { + schema: then, + index + } + }) + ) + .reduce((a, b) => ({ ...a, ...b }), {}); + + return { + propertyNames, + schemasByPropertyName + }; +} + diff --git a/packages/web/src/theme/JSONSchemaViewer/JSONSchemaElements/schemaComposition/allOfSchema.tsx b/packages/web/src/theme/JSONSchemaViewer/JSONSchemaElements/schemaComposition/allOfSchema.tsx index a052b8796..22b7174f8 100644 --- a/packages/web/src/theme/JSONSchemaViewer/JSONSchemaElements/schemaComposition/allOfSchema.tsx +++ b/packages/web/src/theme/JSONSchemaViewer/JSONSchemaElements/schemaComposition/allOfSchema.tsx @@ -10,6 +10,10 @@ import ExclusiveRequiredPropertiesSchema, { detectExclusiveRequiredProperties } from "./ExclusiveRequiredPropertiesSchema"; +import InclusiveRequiredPropertiesSchema, { + detectInclusiveRequiredProperties +} from "./InclusiveRequiredPropertiesSchema"; + export default function allOfSchemaWrapper(props: { schema: Exclude & { allOf: JSONSchema[]; } }) { @@ -25,6 +29,11 @@ export default function allOfSchemaWrapper(props: { return } + const inclusions = detectInclusiveRequiredProperties(schema); + if (inclusions) { + return + } + return ( <> From daf645880309cf8dfa1f2a5ca3b3011c9ca6745f Mon Sep 17 00:00:00 2001 From: "g. nicholas d'andrea" Date: Sun, 27 Apr 2025 23:20:49 -0400 Subject: [PATCH 3/3] Improve description of context schema --- schemas/program/context.schema.yaml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/schemas/program/context.schema.yaml b/schemas/program/context.schema.yaml index 9417f5814..18a67db48 100644 --- a/schemas/program/context.schema.yaml +++ b/schemas/program/context.schema.yaml @@ -3,8 +3,21 @@ $id: "schema:ethdebug/format/program/context" title: ethdebug/format/program/context description: | - A schema for representing the information known at compile-time about the - high-level language concerns at a particular point in code execution. + An **ethdebug/format/program/context** object represents compile-time + information about the high-level runtime execution state at a specific point + in a program's bytecode. + + This schema defines the structure for encoding compile-time knowledge about + the high-level runtime state. Contexts are treated as units of information + that may encompass multiple related or unrelated facts about the program's + state. This may include, e.g., source mapping information (via the `"code"` + property) or information about known variable allocations, etc. + + The interpretation of a context depends on its properties and its + relationship to program elements such as instructions or control flow + structures. For example, a context associated with an instruction may + indicate that the specified conditions hold true following the execution of + that instruction. type: object