expressir 1.2.11-aarch64-linux → 2.4.29-aarch64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.cargo/config.toml +3 -0
- data/.github/scripts/test_installed_gem.rb +34 -0
- data/.github/workflows/codeql.yml +35 -0
- data/.github/workflows/docs.yml +99 -0
- data/.github/workflows/links.yml +100 -0
- data/.github/workflows/native-gems.yml +201 -0
- data/.github/workflows/rake.yml +10 -296
- data/.github/workflows/release.yml +26 -114
- data/.github/workflows/rust-ext.yml +41 -0
- data/.github/workflows/stress.yml +36 -0
- data/.github/workflows/validate_schemas.yml +48 -0
- data/.github/workflows/verify_remarks.yml +33 -0
- data/.gitignore +33 -1
- data/.rubocop.yml +11 -11
- data/.rubocop_todo.yml +297 -0
- data/CHANGELOG.md +159 -0
- data/Gemfile +15 -1
- data/README.adoc +2675 -47
- data/Rakefile +34 -10
- data/TODO.bugs/01-stale-transformer-autoload.md +39 -0
- data/TODO.bugs/02-parser-class-instance-vars.md +36 -0
- data/TODO.bugs/03-builder-mutable-state.md +43 -0
- data/TODO.bugs/04-formatter-public-send-dispatch.md +53 -0
- data/TODO.bugs/05-anonymous-formatter-subclass.md +45 -0
- data/TODO.bugs/06-collection-registry-single-source.md +53 -0
- data/TODO.bugs/07-require-relative-cleanup.md +42 -0
- data/TODO.bugs/08-require-expressir-in-commands.md +34 -0
- data/TODO.bugs/09-parser-split.md +53 -0
- data/TODO.bugs/10-to-s-override.md +42 -0
- data/TODO.bugs/11-parser-class-variables.md +39 -0
- data/TODO.bugs/12-marker-modules-vs-registry.md +64 -0
- data/TODO.bugs/13-string-literal-scanner-limitation.md +52 -0
- data/TODO.bugs/14-model-formatting-leak.md +30 -0
- data/TODO.bugs/15-expression-children-macro.md +27 -0
- data/TODO.bugs/16-pretty-formatter-duplication.md +28 -0
- data/TODO.bugs/17-snake-case-cache-mutable-constant.md +28 -0
- data/TODO.bugs/18-const-get-private-constants.md +30 -0
- data/TODO.bugs/19-format-methods-public.md +22 -0
- data/TODO.bugs/20-coverage-nested-entities-dedup.md +20 -0
- data/TODO.bugs/21-operator-tokens-secondary-dispatch.md +21 -0
- data/TODO.bugs/22-builder-fast-path-wrappers.md +32 -0
- data/TODO.bugs/23-coverage-inverse-maps.md +21 -0
- data/TODO.bugs/24-streaming-builder-complexity.md +19 -0
- data/TODO.bugs/25-debug-puts-in-production.md +21 -0
- data/TODO.bugs/26-generic-entity-children-misplaced.md +21 -0
- data/TODO.bugs/27-package-build-god-method.md +19 -0
- data/TODO.bugs/28-package-god-class.md +30 -0
- data/TODO.bugs/29-validate-ascii-god-class.md +24 -0
- data/TODO.bugs/30-unicode-map-extraction.md +19 -0
- data/TODO.bugs/README.md +43 -0
- data/TODO.max-perf/01-restore-ci-green.md +36 -0
- data/TODO.max-perf/02-streaming-parse-path.md +31 -0
- data/TODO.max-perf/03-cli-parallel-opt-in.md +27 -0
- data/TODO.max-perf/04-benchmark-harness.md +28 -0
- data/TODO.max-perf/05-parallel-fidelity-specs.md +22 -0
- data/TODO.max-perf/06-builder-cpu-audit.md +41 -0
- data/TODO.max-perf/07-upstream-parsanol-roadmap.md +27 -0
- data/TODO.max-perf/08-builder-build-perf.md +45 -0
- data/TODO.max-perf/09-grammar-cold-start.md +25 -0
- data/TODO.max-perf/10-parser-facade-hygiene.md +23 -0
- data/TODO.max-perf/11-ci-green-closeout.md +25 -0
- data/TODO.max-perf/12-require-boot-profile.md +25 -0
- data/TODO.max-perf/13-key-conversion-specs.md +26 -0
- data/TODO.max-perf/14-builder-call-handler-audit.md +28 -0
- data/TODO.parity-ee/00-overview.md +76 -0
- data/TODO.parity-ee/01-annex-g-rule-extraction.md +41 -0
- data/TODO.parity-ee/02-eeng-algorithm-inventory.md +8 -0
- data/TODO.parity-ee/03-eeng-oracle-harness.md +33 -0
- data/TODO.parity-ee/04-shtolo-concatenate.md +44 -0
- data/TODO.parity-ee/05-shtolo-longform-flatten.md +53 -0
- data/TODO.parity-ee/06-interface-scheduling-parity.md +47 -0
- data/TODO.parity-ee/07-semantic-checks-port.md +35 -0
- data/TODO.parity-ee/08-pretty-roundtrip-gate.md +27 -0
- data/TODO.parity-ee/09-smrl-index-and-listing.md +22 -0
- data/TODO.parity-ee/10-interface-dot-graph.md +21 -0
- data/TODO.parity-ee/11-import-eeng-tests.md +79 -0
- data/TODO.parity-ee/12-full-check-catalog.md +67 -0
- data/TODO.parity-ee/13-population-p21.md +54 -0
- data/TODO.parity-ee/14-shtolo-completion.md +44 -0
- data/TODO.parity-ee/15-part28-xml.md +51 -0
- data/TODO.parity-ee/16-compare-patch.md +48 -0
- data/TODO.parity-ee/17-official-tests.md +42 -0
- data/TODO.parity-ee/18-mim-mapping.md +47 -0
- data/TODO.parity-ee/19-architecture.md +97 -0
- data/TODO.parity-ee/parity-matrix.md +108 -0
- data/TODO.refpath-v2/00-overview.md +64 -0
- data/TODO.suma-improvements/00-overview.md +23 -0
- data/TODO.suma-improvements/01-prebuilt-platform-gems.md +33 -0
- data/TODO.suma-improvements/02-suma-e2e.md +39 -0
- data/TODO.suma-improvements/03-item-graph.md +22 -0
- data/TODO.suma-improvements/04-compiled-set-default.md +16 -0
- data/TODO.suma-improvements/05-validation-in-docs.md +17 -0
- data/TODO.suma-improvements/06-memory-remeasure.md +36 -0
- data/TODO.suma-improvements/07-part28-xml.md +15 -0
- data/TODO.suma-improvements/08-windows-gnu-toolchain.md +15 -0
- data/TODO.suma-improvements/09-checker-tranche3.md +13 -0
- data/TODO.suma-improvements/10-expressdoc.md +8 -0
- data/benchmark/srl_benchmark.rb +458 -0
- data/benchmark/srl_native_benchmark.rb +146 -0
- data/benchmark/srl_ruby_benchmark.rb +132 -0
- data/bin/rspec +2 -1
- data/docs/Gemfile +12 -0
- data/docs/_config.yml +141 -0
- data/docs/_guides/changes/changes-format.adoc +778 -0
- data/docs/_guides/changes/importing-eengine.adoc +898 -0
- data/docs/_guides/changes/index.adoc +396 -0
- data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
- data/docs/_guides/changes/validating-changes.adoc +681 -0
- data/docs/_guides/cli/benchmark-performance.adoc +834 -0
- data/docs/_guides/cli/coverage-analysis.adoc +921 -0
- data/docs/_guides/cli/format-schemas.adoc +547 -0
- data/docs/_guides/cli/index.adoc +8 -0
- data/docs/_guides/cli/managing-changes.adoc +927 -0
- data/docs/_guides/cli/validate-ascii.adoc +645 -0
- data/docs/_guides/cli/validate-schemas.adoc +534 -0
- data/docs/_guides/formatter/formatter-architecture.adoc +401 -0
- data/docs/_guides/index.adoc +165 -0
- data/docs/_guides/ler/creating-packages.adoc +664 -0
- data/docs/_guides/ler/index.adoc +305 -0
- data/docs/_guides/ler/loading-packages.adoc +707 -0
- data/docs/_guides/ler/package-formats.adoc +748 -0
- data/docs/_guides/ler/querying-packages.adoc +826 -0
- data/docs/_guides/ler/step-packages.adoc +385 -0
- data/docs/_guides/ler/validating-packages.adoc +750 -0
- data/docs/_guides/liquid/basic-templates.adoc +813 -0
- data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
- data/docs/_guides/liquid/drops-reference.adoc +829 -0
- data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
- data/docs/_guides/liquid/index.adoc +468 -0
- data/docs/_guides/manifests/creating-manifests.adoc +483 -0
- data/docs/_guides/manifests/index.adoc +307 -0
- data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
- data/docs/_guides/manifests/validating-manifests.adoc +713 -0
- data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
- data/docs/_guides/ruby-api/index.adoc +257 -0
- data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
- data/docs/_guides/ruby-api/search-engine.adoc +609 -0
- data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
- data/docs/_pages/data-model.adoc +665 -0
- data/docs/_pages/express-language.adoc +506 -0
- data/docs/_pages/getting-started.adoc +414 -0
- data/docs/_pages/index.adoc +116 -0
- data/docs/_pages/introduction.adoc +256 -0
- data/docs/_pages/ler-packages.adoc +837 -0
- data/docs/_pages/parsers.adoc +709 -0
- data/docs/_pages/schema-manifests.adoc +431 -0
- data/docs/_references/index.adoc +228 -0
- data/docs/_tutorials/creating-ler-package.adoc +735 -0
- data/docs/_tutorials/documentation-coverage.adoc +795 -0
- data/docs/_tutorials/formatting-schemas.adoc +89 -0
- data/docs/_tutorials/index.adoc +231 -0
- data/docs/_tutorials/liquid-templates.adoc +806 -0
- data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
- data/docs/_tutorials/querying-schemas.adoc +751 -0
- data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
- data/docs/index.adoc +242 -0
- data/docs/lychee.toml +90 -0
- data/examples/demo_ler_usage.sh +86 -0
- data/examples/ler/README.md +111 -0
- data/examples/ler/simple_example.ler +0 -0
- data/examples/ler/simple_schema.exp +33 -0
- data/examples/ler_build.rb +75 -0
- data/examples/ler_cli.rb +79 -0
- data/examples/ler_demo_complete.rb +276 -0
- data/examples/ler_query.rb +91 -0
- data/examples/ler_query_examples.rb +305 -0
- data/examples/ler_stats.rb +81 -0
- data/examples/phase3_demo.rb +159 -0
- data/examples/query_demo_simple.rb +131 -0
- data/exe/expressir +6 -17
- data/exe/expressir-format +14 -0
- data/exe/{format-test → expressir-format-test} +8 -7
- data/expressir.gemspec +50 -37
- data/lib/expressir/3.2/expressir_core.so +0 -0
- data/lib/expressir/3.3/expressir_core.so +0 -0
- data/lib/expressir/3.4/expressir_core.so +0 -0
- data/lib/expressir/4.0/expressir_core.so +0 -0
- data/lib/expressir/benchmark.rb +310 -0
- data/lib/expressir/changes/item_change.rb +20 -0
- data/lib/expressir/changes/mapping_change.rb +16 -0
- data/lib/expressir/changes/schema_change.rb +85 -0
- data/lib/expressir/changes/version_change.rb +26 -0
- data/lib/expressir/changes.rb +9 -0
- data/lib/expressir/cli.rb +138 -11
- data/lib/expressir/commands/base.rb +25 -0
- data/lib/expressir/commands/benchmark.rb +59 -0
- data/lib/expressir/commands/benchmark_cache.rb +80 -0
- data/lib/expressir/commands/changes.rb +34 -0
- data/lib/expressir/commands/changes_import_eengine.rb +146 -0
- data/lib/expressir/commands/changes_validate.rb +63 -0
- data/lib/expressir/commands/check.rb +56 -0
- data/lib/expressir/commands/clean.rb +20 -0
- data/lib/expressir/commands/coverage.rb +458 -0
- data/lib/expressir/commands/expand.rb +26 -0
- data/lib/expressir/commands/file_violations.rb +70 -0
- data/lib/expressir/commands/fix.rb +33 -0
- data/lib/expressir/commands/flatten.rb +29 -0
- data/lib/expressir/commands/format.rb +43 -0
- data/lib/expressir/commands/manifest.rb +420 -0
- data/lib/expressir/commands/mapping_validate.rb +68 -0
- data/lib/expressir/commands/non_ascii_character.rb +49 -0
- data/lib/expressir/commands/non_ascii_violation_collection.rb +301 -0
- data/lib/expressir/commands/package.rb +1222 -0
- data/lib/expressir/commands/parity_inputs.rb +160 -0
- data/lib/expressir/commands/validate.rb +106 -0
- data/lib/expressir/commands/validate_ascii.rb +94 -0
- data/lib/expressir/commands/validate_load.rb +91 -0
- data/lib/expressir/commands/version.rb +9 -0
- data/lib/expressir/commands/xsd.rb +23 -0
- data/lib/expressir/commands.rb +30 -0
- data/lib/expressir/config.rb +40 -3
- data/lib/expressir/coverage.rb +510 -0
- data/lib/expressir/eengine/arm_compare_report.rb +23 -0
- data/lib/expressir/eengine/changes_section.rb +16 -0
- data/lib/expressir/eengine/compare_report.rb +69 -0
- data/lib/expressir/eengine/mim_compare_report.rb +23 -0
- data/lib/expressir/eengine/modified_object.rb +21 -0
- data/lib/expressir/eengine.rb +9 -0
- data/lib/expressir/errors.rb +113 -0
- data/lib/expressir/express/adoc_hyperlink_formatter.rb +30 -0
- data/lib/expressir/express/adoc_source_formatter.rb +12 -0
- data/lib/expressir/express/ast_key_converter.rb +114 -0
- data/lib/expressir/express/builder.rb +277 -0
- data/lib/expressir/express/builder_context.rb +22 -0
- data/lib/expressir/express/builder_registry.rb +397 -0
- data/lib/expressir/express/builders/attribute_decl_builder.rb +32 -0
- data/lib/expressir/express/builders/built_in_builder.rb +75 -0
- data/lib/expressir/express/builders/constant_builder.rb +108 -0
- data/lib/expressir/express/builders/declaration_builder.rb +20 -0
- data/lib/expressir/express/builders/derive_clause_builder.rb +14 -0
- data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
- data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
- data/lib/expressir/express/builders/entity_decl_builder.rb +116 -0
- data/lib/expressir/express/builders/explicit_attr_builder.rb +49 -0
- data/lib/expressir/express/builders/expression_builder.rb +416 -0
- data/lib/expressir/express/builders/function_decl_builder.rb +86 -0
- data/lib/expressir/express/builders/helpers.rb +148 -0
- data/lib/expressir/express/builders/interface_builder.rb +151 -0
- data/lib/expressir/express/builders/inverse_attr_builder.rb +43 -0
- data/lib/expressir/express/builders/inverse_attr_type_builder.rb +30 -0
- data/lib/expressir/express/builders/inverse_clause_builder.rb +14 -0
- data/lib/expressir/express/builders/literal_builder.rb +93 -0
- data/lib/expressir/express/builders/procedure_decl_builder.rb +82 -0
- data/lib/expressir/express/builders/qualifier_builder.rb +102 -0
- data/lib/expressir/express/builders/reference_builder.rb +18 -0
- data/lib/expressir/express/builders/rule_decl_builder.rb +97 -0
- data/lib/expressir/express/builders/schema_body_decl_builder.rb +18 -0
- data/lib/expressir/express/builders/schema_decl_builder.rb +56 -0
- data/lib/expressir/express/builders/schema_version_builder.rb +34 -0
- data/lib/expressir/express/builders/simple_id_builder.rb +17 -0
- data/lib/expressir/express/builders/statement_builder.rb +243 -0
- data/lib/expressir/express/builders/subtype_constraint_builder.rb +166 -0
- data/lib/expressir/express/builders/syntax_builder.rb +30 -0
- data/lib/expressir/express/builders/type_builder.rb +238 -0
- data/lib/expressir/express/builders/type_decl_builder.rb +26 -0
- data/lib/expressir/express/builders/unique_clause_builder.rb +20 -0
- data/lib/expressir/express/builders/unique_rule_builder.rb +41 -0
- data/lib/expressir/express/builders/where_clause_builder.rb +20 -0
- data/lib/expressir/express/builders.rb +55 -0
- data/lib/expressir/express/cache.rb +43 -18
- data/lib/expressir/express/checker.rb +812 -0
- data/lib/expressir/express/concatenator.rb +79 -0
- data/lib/expressir/express/core.rb +95 -0
- data/lib/expressir/express/error.rb +124 -0
- data/lib/expressir/express/formatter.rb +89 -1548
- data/lib/expressir/express/formatters/data_types_formatter.rb +362 -0
- data/lib/expressir/express/formatters/declarations_formatter.rb +753 -0
- data/lib/expressir/express/formatters/expressions_formatter.rb +180 -0
- data/lib/expressir/express/formatters/literals_formatter.rb +55 -0
- data/lib/expressir/express/formatters/references_formatter.rb +53 -0
- data/lib/expressir/express/formatters/remark_formatter.rb +270 -0
- data/lib/expressir/express/formatters/remark_item_formatter.rb +28 -0
- data/lib/expressir/express/formatters/statements_formatter.rb +272 -0
- data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +54 -0
- data/lib/expressir/express/formatters.rb +22 -0
- data/lib/expressir/express/grammar/parser.rb +712 -0
- data/lib/expressir/express/grammar.rb +11 -0
- data/lib/expressir/express/hyperlink_formatter.rb +4 -5
- data/lib/expressir/express/interface_dot.rb +105 -0
- data/lib/expressir/express/lazy_repository.rb +211 -0
- data/lib/expressir/express/line_map.rb +48 -0
- data/lib/expressir/express/listing.rb +174 -0
- data/lib/expressir/express/model_traversal.rb +42 -0
- data/lib/expressir/express/model_visitor.rb +11 -10
- data/lib/expressir/express/node_position_index.rb +342 -0
- data/lib/expressir/express/parallel_files.rb +229 -0
- data/lib/expressir/express/parser.rb +501 -62
- data/lib/expressir/express/pretty_formatter.rb +586 -0
- data/lib/expressir/express/pretty_gate.rb +61 -0
- data/lib/expressir/express/refs_overlay.rb +47 -0
- data/lib/expressir/express/remark_attacher.rb +1098 -0
- data/lib/expressir/express/remark_overlay.rb +86 -0
- data/lib/expressir/express/remark_scanner.rb +245 -0
- data/lib/expressir/express/resolve_references_model_visitor.rb +7 -9
- data/lib/expressir/express/schema_block_scanner.rb +137 -0
- data/lib/expressir/express/schema_head_formatter.rb +4 -5
- data/lib/expressir/express/schema_plain_source_formatter.rb +11 -0
- data/lib/expressir/express/schema_source_formatter.rb +15 -0
- data/lib/expressir/express/scope_resolver.rb +223 -0
- data/lib/expressir/express/self_schema_reference.rb +126 -0
- data/lib/expressir/express/shtolo.rb +679 -0
- data/lib/expressir/express/smrl_xml.rb +125 -0
- data/lib/expressir/express/source_formatter.rb +15 -0
- data/lib/expressir/express/streaming_builder.rb +435 -0
- data/lib/expressir/express/xsd.rb +259 -0
- data/lib/expressir/express.rb +53 -0
- data/lib/expressir/liquid.rb +1 -0
- data/lib/expressir/manifest/resolver.rb +210 -0
- data/lib/expressir/manifest/validator.rb +192 -0
- data/lib/expressir/manifest.rb +6 -0
- data/lib/expressir/mapping/refpath.rb +857 -0
- data/lib/expressir/mapping.rb +253 -0
- data/lib/expressir/model/cache.rb +10 -9
- data/lib/expressir/model/concerns.rb +42 -0
- data/lib/expressir/model/data_types/aggregate.rb +8 -13
- data/lib/expressir/model/data_types/array.rb +15 -21
- data/lib/expressir/model/data_types/bag.rb +11 -15
- data/lib/expressir/model/data_types/binary.rb +9 -12
- data/lib/expressir/model/data_types/boolean.rb +7 -2
- data/lib/expressir/model/data_types/enumeration.rb +11 -15
- data/lib/expressir/model/data_types/enumeration_item.rb +5 -7
- data/lib/expressir/model/data_types/generic.rb +6 -8
- data/lib/expressir/model/data_types/generic_entity.rb +11 -13
- data/lib/expressir/model/data_types/integer.rb +7 -2
- data/lib/expressir/model/data_types/list.rb +13 -18
- data/lib/expressir/model/data_types/logical.rb +7 -2
- data/lib/expressir/model/data_types/number.rb +7 -2
- data/lib/expressir/model/data_types/real.rb +7 -9
- data/lib/expressir/model/data_types/select.rb +13 -18
- data/lib/expressir/model/data_types/set.rb +11 -15
- data/lib/expressir/model/data_types/string.rb +9 -12
- data/lib/expressir/model/data_types.rb +25 -0
- data/lib/expressir/model/declarations/attribute.rb +19 -28
- data/lib/expressir/model/declarations/constant.rb +10 -16
- data/lib/expressir/model/declarations/derived_attribute.rb +25 -0
- data/lib/expressir/model/declarations/entity.rb +39 -30
- data/lib/expressir/model/declarations/function.rb +32 -40
- data/lib/expressir/model/declarations/informal_proposition_rule.rb +25 -0
- data/lib/expressir/model/declarations/interface.rb +25 -16
- data/lib/expressir/model/declarations/interface_item.rb +9 -11
- data/lib/expressir/model/declarations/interfaced_item.rb +15 -19
- data/lib/expressir/model/declarations/inverse_attribute.rb +25 -0
- data/lib/expressir/model/declarations/parameter.rb +10 -16
- data/lib/expressir/model/declarations/procedure.rb +30 -37
- data/lib/expressir/model/declarations/remark_item.rb +11 -11
- data/lib/expressir/model/declarations/rule.rb +38 -43
- data/lib/expressir/model/declarations/schema.rb +162 -64
- data/lib/expressir/model/declarations/schema_version.rb +8 -11
- data/lib/expressir/model/declarations/schema_version_item.rb +8 -11
- data/lib/expressir/model/declarations/subtype_constraint.rb +14 -22
- data/lib/expressir/model/declarations/type.rb +18 -18
- data/lib/expressir/model/declarations/unique_rule.rb +8 -13
- data/lib/expressir/model/declarations/variable.rb +10 -16
- data/lib/expressir/model/declarations/where_rule.rb +8 -13
- data/lib/expressir/model/declarations.rb +31 -0
- data/lib/expressir/model/dependency_resolver.rb +268 -0
- data/lib/expressir/model/exp_file.rb +42 -0
- data/lib/expressir/model/expressions/aggregate_initializer.rb +8 -9
- data/lib/expressir/model/expressions/aggregate_initializer_item.rb +10 -12
- data/lib/expressir/model/expressions/binary_expression.rb +42 -36
- data/lib/expressir/model/expressions/entity_constructor.rb +10 -12
- data/lib/expressir/model/expressions/function_call.rb +10 -12
- data/lib/expressir/model/expressions/interval.rb +18 -23
- data/lib/expressir/model/expressions/query_expression.rb +11 -15
- data/lib/expressir/model/expressions/unary_expression.rb +13 -15
- data/lib/expressir/model/expressions.rb +18 -0
- data/lib/expressir/model/identifier.rb +18 -26
- data/lib/expressir/model/indexes/entity_index.rb +103 -0
- data/lib/expressir/model/indexes/item_graph.rb +185 -0
- data/lib/expressir/model/indexes/reference_index.rb +148 -0
- data/lib/expressir/model/indexes/type_index.rb +149 -0
- data/lib/expressir/model/indexes.rb +12 -0
- data/lib/expressir/model/interface_validator.rb +384 -0
- data/lib/expressir/model/literals/binary.rb +7 -9
- data/lib/expressir/model/literals/integer.rb +7 -9
- data/lib/expressir/model/literals/logical.rb +10 -12
- data/lib/expressir/model/literals/real.rb +7 -9
- data/lib/expressir/model/literals/string.rb +10 -12
- data/lib/expressir/model/literals.rb +13 -0
- data/lib/expressir/model/model_element.rb +286 -117
- data/lib/expressir/model/references/attribute_reference.rb +9 -12
- data/lib/expressir/model/references/group_reference.rb +9 -12
- data/lib/expressir/model/references/index_reference.rb +11 -15
- data/lib/expressir/model/references/simple_reference.rb +11 -14
- data/lib/expressir/model/references.rb +12 -0
- data/lib/expressir/model/remark_format.rb +17 -0
- data/lib/expressir/model/remark_info.rb +92 -0
- data/lib/expressir/model/remark_placement.rb +42 -0
- data/lib/expressir/model/repository.rb +472 -12
- data/lib/expressir/model/repository_validator.rb +293 -0
- data/lib/expressir/model/search_engine.rb +551 -0
- data/lib/expressir/model/statements/alias.rb +12 -16
- data/lib/expressir/model/statements/assignment.rb +12 -11
- data/lib/expressir/model/statements/case.rb +31 -14
- data/lib/expressir/model/statements/case_action.rb +9 -11
- data/lib/expressir/model/statements/compound.rb +10 -8
- data/lib/expressir/model/statements/escape.rb +10 -2
- data/lib/expressir/model/statements/if.rb +15 -14
- data/lib/expressir/model/statements/null.rb +10 -2
- data/lib/expressir/model/statements/procedure_call.rb +11 -11
- data/lib/expressir/model/statements/repeat.rb +21 -28
- data/lib/expressir/model/statements/return.rb +9 -8
- data/lib/expressir/model/statements/skip.rb +10 -2
- data/lib/expressir/model/statements.rb +20 -0
- data/lib/expressir/model/supertype_expressions/binary_supertype_expression.rb +13 -17
- data/lib/expressir/model/supertype_expressions/oneof_supertype_expression.rb +7 -9
- data/lib/expressir/model/supertype_expressions.rb +12 -0
- data/lib/expressir/model.rb +38 -78
- data/lib/expressir/package/builder.rb +231 -0
- data/lib/expressir/package/metadata.rb +79 -0
- data/lib/expressir/package/reader.rb +149 -0
- data/lib/expressir/package.rb +8 -0
- data/lib/expressir/schema_manifest.rb +159 -0
- data/lib/expressir/schema_manifest_entry.rb +15 -0
- data/lib/expressir/version.rb +6 -1
- data/lib/expressir.rb +79 -9
- data/lib/tasks/verify_remarks.rake +16 -0
- data/rakelib/native.rake +24 -0
- data/rakelib/oracle.rake +52 -0
- data/rakelib/verify_remarks.rake +16 -0
- metadata +431 -129
- data/.cross_rubies +0 -20
- data/.gitmodules +0 -6
- data/.yardopts +0 -11
- data/docs/development.md +0 -90
- data/exe/format +0 -18
- data/exe/generate-parser +0 -51
- data/lib/expressir/cli/ui.rb +0 -36
- data/lib/expressir/express/2.7/express_parser.so +0 -0
- data/lib/expressir/express/3.0/express_parser.so +0 -0
- data/lib/expressir/express/3.1/express_parser.so +0 -0
- data/lib/expressir/express/3.2/express_parser.so +0 -0
- data/lib/expressir/express/visitor.rb +0 -2588
- data/lib/expressir/model/data_type.rb +0 -9
- data/lib/expressir/model/declaration.rb +0 -9
- data/lib/expressir/model/expression.rb +0 -9
- data/lib/expressir/model/literal.rb +0 -9
- data/lib/expressir/model/reference.rb +0 -9
- data/lib/expressir/model/statement.rb +0 -9
- data/lib/expressir/model/supertype_expression.rb +0 -9
- data/rakelib/antlr4-native.rake +0 -161
- data/rakelib/cross-ruby.rake +0 -368
- data/spec/acceptance/version_spec.rb +0 -27
- data/spec/expressir/express/cache_spec.rb +0 -89
- data/spec/expressir/express/formatter_spec.rb +0 -173
- data/spec/expressir/express/parser_spec.rb +0 -141
- data/spec/expressir/model/model_element_spec.rb +0 -318
- data/spec/spec_helper.rb +0 -24
- data/spec/support/console_helper.rb +0 -29
- data/spec/syntax/multiple.exp +0 -23
- data/spec/syntax/multiple.yaml +0 -198
- data/spec/syntax/multiple_formatted.exp +0 -71
- data/spec/syntax/multiple_hyperlink_formatted.exp +0 -71
- data/spec/syntax/multiple_schema_head_hyperlink_formatted.exp +0 -13
- data/spec/syntax/remark.exp +0 -193
- data/spec/syntax/remark.yaml +0 -471
- data/spec/syntax/remark_formatted.exp +0 -228
- data/spec/syntax/single.exp +0 -4
- data/spec/syntax/single.yaml +0 -18
- data/spec/syntax/single_formatted.exp +0 -10
- data/spec/syntax/single_formatted.yaml +0 -36
- data/spec/syntax/syntax.exp +0 -333
- data/spec/syntax/syntax.yaml +0 -3509
- data/spec/syntax/syntax_formatted.exp +0 -902
- data/spec/syntax/syntax_hyperlink_formatted.exp +0 -902
- data/spec/syntax/syntax_schema_head_formatted.exp +0 -18
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
require "pathname"
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
# Coverage module for calculating documentation coverage of EXPRESS entities
|
|
5
|
+
module Coverage
|
|
6
|
+
# Single source of truth: EXPRESS type name → Ruby class name pairs.
|
|
7
|
+
# ENTITY_TYPE_MAP and CLASS_TO_EXPRESS_TYPE_MAP are derived from this
|
|
8
|
+
# so the two never drift out of sync.
|
|
9
|
+
TYPE_PAIRS = [
|
|
10
|
+
["TYPE", "Expressir::Model::Declarations::Type"],
|
|
11
|
+
["ENTITY", "Expressir::Model::Declarations::Entity"],
|
|
12
|
+
["CONSTANT", "Expressir::Model::Declarations::Constant"],
|
|
13
|
+
["FUNCTION", "Expressir::Model::Declarations::Function"],
|
|
14
|
+
["RULE", "Expressir::Model::Declarations::Rule"],
|
|
15
|
+
["PROCEDURE", "Expressir::Model::Declarations::Procedure"],
|
|
16
|
+
["SUBTYPE_CONSTRAINT", "Expressir::Model::Declarations::SubtypeConstraint"],
|
|
17
|
+
["PARAMETER", "Expressir::Model::Declarations::Parameter"],
|
|
18
|
+
["VARIABLE", "Expressir::Model::Declarations::Variable"],
|
|
19
|
+
["ATTRIBUTE", "Expressir::Model::Declarations::Attribute"],
|
|
20
|
+
["DERIVED_ATTRIBUTE", "Expressir::Model::Declarations::DerivedAttribute"],
|
|
21
|
+
["INVERSE_ATTRIBUTE", "Expressir::Model::Declarations::InverseAttribute"],
|
|
22
|
+
["UNIQUE_RULE", "Expressir::Model::Declarations::UniqueRule"],
|
|
23
|
+
["WHERE_RULE", "Expressir::Model::Declarations::WhereRule"],
|
|
24
|
+
["ENUMERATION_ITEM", "Expressir::Model::DataTypes::EnumerationItem"],
|
|
25
|
+
["INTERFACE", "Expressir::Model::Declarations::Interface"],
|
|
26
|
+
["INTERFACE_ITEM", "Expressir::Model::Declarations::InterfaceItem"],
|
|
27
|
+
["INTERFACED_ITEM", "Expressir::Model::Declarations::InterfacedItem"],
|
|
28
|
+
["SCHEMA_VERSION", "Expressir::Model::Declarations::SchemaVersion"],
|
|
29
|
+
["SCHEMA_VERSION_ITEM", "Expressir::Model::Declarations::SchemaVersionItem"],
|
|
30
|
+
].freeze
|
|
31
|
+
|
|
32
|
+
# EXPRESS entity type name → Ruby class name.
|
|
33
|
+
ENTITY_TYPE_MAP = TYPE_PAIRS.to_h.freeze
|
|
34
|
+
|
|
35
|
+
# Short Ruby class name → EXPRESS entity type name.
|
|
36
|
+
CLASS_TO_EXPRESS_TYPE_MAP = TYPE_PAIRS.to_h do |express_name, ruby_class|
|
|
37
|
+
[ruby_class.split("::").last, express_name]
|
|
38
|
+
end.freeze
|
|
39
|
+
|
|
40
|
+
# Available TYPE subtypes based on data types
|
|
41
|
+
TYPE_SUBTYPES = %w[
|
|
42
|
+
AGGREGATE ARRAY BAG BINARY BOOLEAN ENUMERATION GENERIC GENERIC_ENTITY
|
|
43
|
+
INTEGER LIST LOGICAL NUMBER REAL SELECT SET STRING
|
|
44
|
+
].freeze
|
|
45
|
+
# Represents a documentation coverage report for EXPRESS schemas
|
|
46
|
+
class Report
|
|
47
|
+
attr_reader :repository, :schema_reports, :total_entities, :documented_entities,
|
|
48
|
+
:undocumented_entities, :ignored_files
|
|
49
|
+
|
|
50
|
+
# Initialize a coverage report
|
|
51
|
+
# @param repository [Expressir::Model::Repository] The repository to analyze
|
|
52
|
+
# @param skip_types [Array<String>] Array of entity type names to skip from coverage
|
|
53
|
+
# @param ignored_files [Hash] Hash mapping absolute file paths to their matched patterns
|
|
54
|
+
def initialize(repository, skip_types = [], ignored_files = {})
|
|
55
|
+
@repository = repository
|
|
56
|
+
@skip_types = skip_types
|
|
57
|
+
@ignored_files = ignored_files
|
|
58
|
+
@schema_reports = []
|
|
59
|
+
@total_entities = []
|
|
60
|
+
@documented_entities = []
|
|
61
|
+
@undocumented_entities = []
|
|
62
|
+
|
|
63
|
+
process_repository
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Create a report from a repository
|
|
67
|
+
# @param repository [Expressir::Model::Repository] The repository to analyze
|
|
68
|
+
# @param skip_types [Array<String>] Array of entity type names to skip from coverage
|
|
69
|
+
# @param ignored_files [Hash] Hash mapping absolute file paths to their matched patterns
|
|
70
|
+
# @return [Report] The coverage report
|
|
71
|
+
def self.from_repository(repository, skip_types = [], ignored_files = {})
|
|
72
|
+
new(repository, skip_types, ignored_files)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Create a report from a schema file
|
|
76
|
+
# @param path [String] Path to the schema file
|
|
77
|
+
# @param skip_types [Array<String>] Array of entity type names to skip from coverage
|
|
78
|
+
# @param ignored_files [Hash] Hash mapping absolute file paths to their matched patterns
|
|
79
|
+
# @return [Report] The coverage report
|
|
80
|
+
def self.from_file(path, skip_types = [], ignored_files = {})
|
|
81
|
+
repository = Expressir::Express::Parser.from_file(path)
|
|
82
|
+
new(repository, skip_types, ignored_files)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Calculate the overall coverage percentage
|
|
86
|
+
# @return [Float] The coverage percentage
|
|
87
|
+
def coverage_percentage
|
|
88
|
+
return 100.0 if @total_entities.empty?
|
|
89
|
+
|
|
90
|
+
(@documented_entities.size.to_f / @total_entities.size) * 100
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Get file-level reports
|
|
94
|
+
# @return [Array<Hash>] Array of file report hashes
|
|
95
|
+
def file_reports
|
|
96
|
+
@schema_reports.map do |report|
|
|
97
|
+
absolute_path = report[:schema].file
|
|
98
|
+
relative_path = begin
|
|
99
|
+
Pathname.new(absolute_path).relative_path_from(Pathname.pwd).to_s
|
|
100
|
+
rescue ArgumentError
|
|
101
|
+
# If paths are on different drives or otherwise incompatible,
|
|
102
|
+
# fall back to the absolute path
|
|
103
|
+
absolute_path
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
file_report = {
|
|
107
|
+
"file" => relative_path,
|
|
108
|
+
"file_basename" => File.basename(absolute_path),
|
|
109
|
+
"directory" => File.dirname(absolute_path),
|
|
110
|
+
"total" => report[:total].size,
|
|
111
|
+
"documented" => report[:documented].size,
|
|
112
|
+
"undocumented" => report[:undocumented],
|
|
113
|
+
"coverage" => report[:coverage],
|
|
114
|
+
"ignored" => report[:ignored] || false,
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# Add matched pattern for ignored files
|
|
118
|
+
if report[:ignored] && report[:matched_pattern]
|
|
119
|
+
file_report["matched_pattern"] = report[:matched_pattern]
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
file_report
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Get ignored file reports
|
|
127
|
+
# @return [Array<Hash>] Array of ignored file report hashes
|
|
128
|
+
def ignored_file_reports
|
|
129
|
+
@schema_reports.select { |report| report[:ignored] }.map do |report|
|
|
130
|
+
absolute_path = report[:schema].file
|
|
131
|
+
relative_path = begin
|
|
132
|
+
Pathname.new(absolute_path).relative_path_from(Pathname.pwd).to_s
|
|
133
|
+
rescue ArgumentError
|
|
134
|
+
# If paths are on different drives or otherwise incompatible,
|
|
135
|
+
# fall back to the absolute path
|
|
136
|
+
absolute_path
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
{
|
|
140
|
+
"file" => relative_path,
|
|
141
|
+
"file_basename" => File.basename(absolute_path),
|
|
142
|
+
"directory" => File.dirname(absolute_path),
|
|
143
|
+
"total" => report[:total].size,
|
|
144
|
+
"documented" => report[:documented].size,
|
|
145
|
+
"undocumented" => report[:undocumented],
|
|
146
|
+
"coverage" => report[:coverage],
|
|
147
|
+
"matched_pattern" => report[:matched_pattern],
|
|
148
|
+
}
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Get directory-level reports
|
|
153
|
+
# @return [Array<Hash>] Array of directory report hashes
|
|
154
|
+
def directory_reports
|
|
155
|
+
# Group by directory (absolute path)
|
|
156
|
+
by_directory = file_reports.group_by { |r| r["directory"] }
|
|
157
|
+
|
|
158
|
+
# Aggregate stats for each directory
|
|
159
|
+
by_directory.map do |directory, reports|
|
|
160
|
+
# Convert directory to relative path
|
|
161
|
+
relative_directory = begin
|
|
162
|
+
Pathname.new(directory).relative_path_from(Pathname.pwd).to_s
|
|
163
|
+
rescue ArgumentError
|
|
164
|
+
# If paths are on different drives or otherwise incompatible,
|
|
165
|
+
# fall back to the absolute path
|
|
166
|
+
directory
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
total = reports.sum { |r| r["total"] }
|
|
170
|
+
documented = reports.sum { |r| r["documented"] }
|
|
171
|
+
coverage = total.positive? ? (documented.to_f / total) * 100 : 100.0
|
|
172
|
+
|
|
173
|
+
{
|
|
174
|
+
"directory" => relative_directory,
|
|
175
|
+
"total" => total,
|
|
176
|
+
"documented" => documented,
|
|
177
|
+
"undocumented" => total - documented,
|
|
178
|
+
"coverage" => coverage,
|
|
179
|
+
"files" => reports.size,
|
|
180
|
+
}
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Convert report to a hash representation
|
|
185
|
+
# @return [Hash] The report as a hash
|
|
186
|
+
def to_h
|
|
187
|
+
{
|
|
188
|
+
"overall" => {
|
|
189
|
+
"total" => @total_entities.size,
|
|
190
|
+
"documented" => @documented_entities.size,
|
|
191
|
+
"undocumented" => @undocumented_entities.size,
|
|
192
|
+
"coverage" => coverage_percentage,
|
|
193
|
+
},
|
|
194
|
+
"directories" => directory_reports,
|
|
195
|
+
"files" => file_reports,
|
|
196
|
+
}
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
private
|
|
200
|
+
|
|
201
|
+
# Process the repository and collect coverage information
|
|
202
|
+
def process_repository
|
|
203
|
+
return unless @repository
|
|
204
|
+
|
|
205
|
+
@repository.schemas.each do |schema|
|
|
206
|
+
schema_report = process_schema(schema)
|
|
207
|
+
@schema_reports << schema_report
|
|
208
|
+
|
|
209
|
+
# Only include non-ignored files in overall statistics
|
|
210
|
+
unless schema_report[:ignored]
|
|
211
|
+
@total_entities.concat(schema_report[:total])
|
|
212
|
+
@documented_entities.concat(schema_report[:documented])
|
|
213
|
+
@undocumented_entities.concat(schema_report[:undocumented].map do |entity|
|
|
214
|
+
{ schema: schema.id, entity: entity }
|
|
215
|
+
end)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Process a schema and collect coverage information
|
|
221
|
+
# @param schema [Expressir::Model::Declarations::Schema] The schema to analyze
|
|
222
|
+
# @return [Hash] A hash with coverage information
|
|
223
|
+
def process_schema(schema)
|
|
224
|
+
entities = Expressir::Coverage.find_entities(schema, @skip_types)
|
|
225
|
+
documented = entities.select do |e|
|
|
226
|
+
Expressir::Coverage.entity_documented?(e)
|
|
227
|
+
end
|
|
228
|
+
undocumented = entities - documented
|
|
229
|
+
|
|
230
|
+
coverage = entities.empty? ? 100.0 : (documented.size.to_f / entities.size) * 100
|
|
231
|
+
|
|
232
|
+
# Check if this schema file is ignored
|
|
233
|
+
schema_file = File.expand_path(schema.file) if schema.file
|
|
234
|
+
ignored = @ignored_files.key?(schema_file)
|
|
235
|
+
matched_pattern = @ignored_files[schema_file] if ignored
|
|
236
|
+
|
|
237
|
+
{
|
|
238
|
+
schema: schema,
|
|
239
|
+
total: entities,
|
|
240
|
+
documented: documented,
|
|
241
|
+
undocumented: undocumented.map { |e| format_entity(e) },
|
|
242
|
+
coverage: coverage,
|
|
243
|
+
ignored: ignored,
|
|
244
|
+
matched_pattern: matched_pattern,
|
|
245
|
+
}
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Format an entity for display
|
|
249
|
+
# @param entity [Expressir::Model::ModelElement] The entity to format
|
|
250
|
+
# @return [Hash] A hash with type and name of the entity
|
|
251
|
+
def format_entity(entity)
|
|
252
|
+
# Get class name (e.g., "Type" from "Expressir::Model::Declarations::Type")
|
|
253
|
+
type_name = entity.class.name.split("::").last
|
|
254
|
+
|
|
255
|
+
# Use proper mapping to EXPRESS convention
|
|
256
|
+
express_type = CLASS_TO_EXPRESS_TYPE_MAP[type_name] || type_name.upcase
|
|
257
|
+
|
|
258
|
+
# Return structured format
|
|
259
|
+
{
|
|
260
|
+
"type" => express_type,
|
|
261
|
+
"name" => entity.id.to_s,
|
|
262
|
+
}
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# Check if an entity has documentation (remarks)
|
|
267
|
+
# @param entity [Expressir::Model::ModelElement] The entity to check
|
|
268
|
+
# @return [Boolean] True if the entity has documentation
|
|
269
|
+
def self.entity_documented?(entity)
|
|
270
|
+
# Check for direct remarks (types with Identifier module have remarks)
|
|
271
|
+
if entity.is_a?(Model::HasRemarks) && entity.remarks && !entity.remarks.empty?
|
|
272
|
+
return true
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Check for remark_items (types with Identifier module have remark_items)
|
|
276
|
+
if entity.is_a?(Model::HasRemarkItems) && entity.remark_items && !entity.remark_items.empty?
|
|
277
|
+
return true
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# For schema entities, check if there's a remark_item with their ID
|
|
281
|
+
parent = entity.parent
|
|
282
|
+
if parent.is_a?(Model::HasRemarkItems) && parent.remark_items
|
|
283
|
+
entity_id = entity.id.to_s.downcase
|
|
284
|
+
parent.remark_items.any? do |item|
|
|
285
|
+
item.id.to_s.downcase == entity_id || item.id.to_s.downcase.include?("#{entity_id}.")
|
|
286
|
+
end
|
|
287
|
+
else
|
|
288
|
+
false
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Find all entities in a schema or repository
|
|
293
|
+
# @param schema_or_repo [Expressir::Model::Declarations::Schema, Expressir::Model::Repository, Expressir::Model::ExpFile] The schema, repository, or file to analyze
|
|
294
|
+
# @param skip_types [Array<String>] Array of entity type names to skip from coverage
|
|
295
|
+
# @return [Array<Expressir::Model::ModelElement>] Array of entities
|
|
296
|
+
def self.find_entities(schema_or_repo, skip_types = [])
|
|
297
|
+
entities = []
|
|
298
|
+
|
|
299
|
+
# Handle repository, exp_file, and schema inputs
|
|
300
|
+
if schema_or_repo.is_a?(Expressir::Model::Repository)
|
|
301
|
+
# If it's a repository, process all files
|
|
302
|
+
schema_or_repo.files&.each do |file|
|
|
303
|
+
file.schemas&.each do |schema|
|
|
304
|
+
entities.concat(find_entities_in_schema(schema))
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
elsif schema_or_repo.is_a?(Expressir::Model::ExpFile)
|
|
308
|
+
# If it's an ExpFile, process all schemas in the file
|
|
309
|
+
schema_or_repo.schemas&.each do |schema|
|
|
310
|
+
entities.concat(find_entities_in_schema(schema))
|
|
311
|
+
end
|
|
312
|
+
else
|
|
313
|
+
# If it's a schema, process it directly
|
|
314
|
+
entities.concat(find_entities_in_schema(schema_or_repo))
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
# Filter out nil elements and ensure all have IDs
|
|
318
|
+
# Note: Some ModelElement types (like Interface) don't have id
|
|
319
|
+
entities = entities.compact.select do |e|
|
|
320
|
+
e.is_a?(Model::HasId) && e.id
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# Filter out skipped entity types
|
|
324
|
+
apply_exclusions(entities, skip_types)
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
# Find all entities in a single schema
|
|
328
|
+
# @param schema [Expressir::Model::Declarations::Schema] The schema to analyze
|
|
329
|
+
# @return [Array<Expressir::Model::ModelElement>] Array of entities
|
|
330
|
+
def self.find_entities_in_schema(schema)
|
|
331
|
+
entities = []
|
|
332
|
+
|
|
333
|
+
# Add all schema-level entities
|
|
334
|
+
entities.concat(schema.constants) if schema.constants
|
|
335
|
+
entities.concat(schema.types) if schema.types
|
|
336
|
+
entities.concat(schema.entities) if schema.entities
|
|
337
|
+
entities.concat(schema.functions) if schema.functions
|
|
338
|
+
entities.concat(schema.rules) if schema.rules
|
|
339
|
+
entities.concat(schema.procedures) if schema.procedures
|
|
340
|
+
entities.concat(schema.subtype_constraints) if schema.subtype_constraints
|
|
341
|
+
entities.concat(schema.interfaces) if schema.interfaces
|
|
342
|
+
|
|
343
|
+
# Add nested entities recursively
|
|
344
|
+
entities.concat(find_nested_entities(schema))
|
|
345
|
+
|
|
346
|
+
entities
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
# Find all nested entities within a container (schema, entity, function, etc.)
|
|
350
|
+
# @param container [Expressir::Model::ModelElement] The container to search
|
|
351
|
+
# @return [Array<Expressir::Model::ModelElement>] Array of nested entities
|
|
352
|
+
def self.find_nested_entities(container)
|
|
353
|
+
entities = []
|
|
354
|
+
|
|
355
|
+
# Handle different container types
|
|
356
|
+
case container
|
|
357
|
+
when Expressir::Model::Declarations::Schema
|
|
358
|
+
# Schema-level nested entities
|
|
359
|
+
container.types&.each do |type|
|
|
360
|
+
entities.concat(find_nested_entities(type))
|
|
361
|
+
end
|
|
362
|
+
container.entities&.each do |entity|
|
|
363
|
+
entities.concat(find_nested_entities(entity))
|
|
364
|
+
end
|
|
365
|
+
container.functions&.each do |function|
|
|
366
|
+
entities.concat(find_nested_entities(function))
|
|
367
|
+
end
|
|
368
|
+
container.rules&.each do |rule|
|
|
369
|
+
entities.concat(find_nested_entities(rule))
|
|
370
|
+
end
|
|
371
|
+
container.procedures&.each do |procedure|
|
|
372
|
+
entities.concat(find_nested_entities(procedure))
|
|
373
|
+
end
|
|
374
|
+
container.interfaces&.each do |interface|
|
|
375
|
+
entities.concat(find_nested_entities(interface))
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
when Expressir::Model::Declarations::Type
|
|
379
|
+
# Type nested entities
|
|
380
|
+
if container.enumeration_items
|
|
381
|
+
entities.concat(container.enumeration_items)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
when Expressir::Model::Declarations::Entity
|
|
385
|
+
# Entity nested entities
|
|
386
|
+
entities.concat(container.attributes) if container.attributes
|
|
387
|
+
entities.concat(container.unique_rules) if container.unique_rules
|
|
388
|
+
entities.concat(container.where_rules) if container.where_rules
|
|
389
|
+
|
|
390
|
+
when Expressir::Model::Declarations::Function,
|
|
391
|
+
Expressir::Model::Declarations::Procedure,
|
|
392
|
+
Expressir::Model::Declarations::Rule
|
|
393
|
+
# All three scope containers follow the same nested-entity pattern.
|
|
394
|
+
# Derive the collection list from the model's own declaration rather
|
|
395
|
+
# than maintaining three separate hand-coded branches.
|
|
396
|
+
nested_attrs = container.class.collection_attributes_list - %i[
|
|
397
|
+
statements remark_items where_rules informal_propositions applies_to
|
|
398
|
+
]
|
|
399
|
+
nested_attrs.each do |attr|
|
|
400
|
+
collection = container.public_send(attr)
|
|
401
|
+
entities.concat(collection) if collection.is_a?(Array)
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
# Recursively find nested entities in nested scope containers
|
|
405
|
+
%i[types entities functions procedures].each do |attr|
|
|
406
|
+
collection = container.public_send(attr)
|
|
407
|
+
collection&.each { |item| entities.concat(find_nested_entities(item)) }
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
when Expressir::Model::Declarations::Interface
|
|
411
|
+
# Interface nested entities
|
|
412
|
+
entities.concat(container.items) if container.items
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
entities
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
# Apply exclusions to filter out entities based on skip_types (supports both simple and TYPE:SUBTYPE syntax)
|
|
419
|
+
# @param entities [Array<Expressir::Model::ModelElement>] The entities to filter
|
|
420
|
+
# @param exclusions [Array<String>] Array of entity type names to exclude from coverage
|
|
421
|
+
# @return [Array<Expressir::Model::ModelElement>] Filtered entities
|
|
422
|
+
def self.apply_exclusions(entities, exclusions)
|
|
423
|
+
filter_skipped_entities(entities, exclusions)
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
# Filter out entities based on skip_types (supports both simple and TYPE:SUBTYPE syntax)
|
|
427
|
+
# @param entities [Array<Expressir::Model::ModelElement>] The entities to filter
|
|
428
|
+
# @param skip_types [Array<String>] Array of entity type names to skip from coverage
|
|
429
|
+
# @return [Array<Expressir::Model::ModelElement>] Filtered entities
|
|
430
|
+
def self.filter_skipped_entities(entities, skip_types)
|
|
431
|
+
return entities if skip_types.empty?
|
|
432
|
+
|
|
433
|
+
# Parse skip_types into simple types, TYPE subtypes, and FUNCTION subtypes
|
|
434
|
+
simple_skips = []
|
|
435
|
+
type_subtype_skips = []
|
|
436
|
+
function_subtype_skips = []
|
|
437
|
+
|
|
438
|
+
skip_types.each do |skip_type|
|
|
439
|
+
if skip_type.include?(":")
|
|
440
|
+
# Handle TYPE:SUBTYPE and FUNCTION:SUBTYPE format
|
|
441
|
+
main_type, subtype = skip_type.split(":", 2)
|
|
442
|
+
if main_type == "TYPE" && TYPE_SUBTYPES.include?(subtype)
|
|
443
|
+
type_subtype_skips << subtype
|
|
444
|
+
elsif main_type == "FUNCTION" && subtype == "INNER"
|
|
445
|
+
function_subtype_skips << subtype
|
|
446
|
+
end
|
|
447
|
+
else
|
|
448
|
+
# Handle simple type format
|
|
449
|
+
simple_skips << skip_type
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
# Filter entities
|
|
454
|
+
entities.reject do |entity|
|
|
455
|
+
entity_class = entity.class.name
|
|
456
|
+
|
|
457
|
+
# Check simple type exclusions
|
|
458
|
+
# Convert entity class to EXPRESS type name for comparison
|
|
459
|
+
class_name = entity_class.split("::").last
|
|
460
|
+
express_type = CLASS_TO_EXPRESS_TYPE_MAP[class_name] || class_name.upcase
|
|
461
|
+
|
|
462
|
+
if simple_skips.include?(express_type)
|
|
463
|
+
true
|
|
464
|
+
# Check TYPE subtype exclusions
|
|
465
|
+
elsif entity_class == "Expressir::Model::Declarations::Type" && type_subtype_skips.any?
|
|
466
|
+
entity_subtype = get_type_subtype(entity)
|
|
467
|
+
type_subtype_skips.include?(entity_subtype)
|
|
468
|
+
# Check FUNCTION:INNER exclusions
|
|
469
|
+
elsif entity_class == "Expressir::Model::Declarations::Function" && function_subtype_skips.include?("INNER")
|
|
470
|
+
inner_function?(entity)
|
|
471
|
+
else
|
|
472
|
+
false
|
|
473
|
+
end
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
# Get the subtype of a TYPE entity based on its underlying_type
|
|
478
|
+
# @param type_entity [Expressir::Model::Declarations::Type] The TYPE entity
|
|
479
|
+
# @return [String] The subtype name (e.g., "SELECT", "ENUMERATION")
|
|
480
|
+
def self.get_type_subtype(type_entity)
|
|
481
|
+
return nil unless type_entity.is_a?(Model::Declarations::Type) && type_entity.underlying_type
|
|
482
|
+
|
|
483
|
+
# Get the class name of the underlying type
|
|
484
|
+
underlying_class = type_entity.underlying_type.class.name
|
|
485
|
+
|
|
486
|
+
# Extract the data type name (e.g., "Select" from "Expressir::Model::DataTypes::Select")
|
|
487
|
+
if underlying_class.start_with?("Expressir::Model::DataTypes::")
|
|
488
|
+
data_type_name = underlying_class.split("::").last
|
|
489
|
+
# Convert to uppercase (e.g., "Select" -> "SELECT")
|
|
490
|
+
data_type_name.upcase
|
|
491
|
+
else
|
|
492
|
+
# For other types, try to extract the last part of the class name
|
|
493
|
+
underlying_class.split("::").last&.upcase
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
# Check if a function is an inner function (nested within another function, rule, or procedure)
|
|
498
|
+
# @param function_entity [Expressir::Model::Declarations::Function] The function entity to check
|
|
499
|
+
# @return [Boolean] True if the function is nested within another function, rule, or procedure
|
|
500
|
+
def self.inner_function?(function_entity)
|
|
501
|
+
return false unless function_entity.is_a?(Model::Declarations::Function) && function_entity.parent
|
|
502
|
+
|
|
503
|
+
# Check if the parent is a function, rule, or procedure (not a schema)
|
|
504
|
+
parent = function_entity.parent
|
|
505
|
+
parent.is_a?(Expressir::Model::Declarations::Function) ||
|
|
506
|
+
parent.is_a?(Expressir::Model::Declarations::Rule) ||
|
|
507
|
+
parent.is_a?(Expressir::Model::Declarations::Procedure)
|
|
508
|
+
end
|
|
509
|
+
end
|
|
510
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Eengine
|
|
5
|
+
# Represents an Eengine ARM comparison XML report
|
|
6
|
+
class ArmCompareReport < Lutaml::Model::Serializable
|
|
7
|
+
attribute :modifications, ChangesSection
|
|
8
|
+
attribute :additions, ChangesSection
|
|
9
|
+
attribute :deletions, ChangesSection
|
|
10
|
+
|
|
11
|
+
xml do
|
|
12
|
+
element "arm.changes"
|
|
13
|
+
map_element "arm.modifications", to: :modifications
|
|
14
|
+
map_element "arm.additions", to: :additions
|
|
15
|
+
map_element "arm.deletions", to: :deletions
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def mode
|
|
19
|
+
"arm"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Eengine
|
|
5
|
+
# Represents a section of changes (modifications, additions, or deletions)
|
|
6
|
+
# in an Eengine comparison report
|
|
7
|
+
class ChangesSection < Lutaml::Model::Serializable
|
|
8
|
+
attribute :modified_objects, ModifiedObject, collection: true
|
|
9
|
+
|
|
10
|
+
xml do
|
|
11
|
+
element "changes.section"
|
|
12
|
+
map_element "modified.object", to: :modified_objects
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Eengine
|
|
5
|
+
# Represents an Eengine comparison XML report
|
|
6
|
+
# Supports three modes: ARM, MIM, and Schema
|
|
7
|
+
class CompareReport < Lutaml::Model::Serializable
|
|
8
|
+
attribute :modifications, ChangesSection
|
|
9
|
+
attribute :additions, ChangesSection
|
|
10
|
+
attribute :deletions, ChangesSection
|
|
11
|
+
|
|
12
|
+
xml do
|
|
13
|
+
element "schema.changes"
|
|
14
|
+
map_element "schema.modifications", to: :modifications
|
|
15
|
+
map_element "schema.additions", to: :additions
|
|
16
|
+
map_element "schema.deletions", to: :deletions
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
# Parse XML and return appropriate report class based on mode
|
|
21
|
+
#
|
|
22
|
+
# @param xml_content [String] XML content
|
|
23
|
+
# @return [CompareReport, ArmCompareReport, MimCompareReport]
|
|
24
|
+
def from_xml(xml_content)
|
|
25
|
+
mode = detect_mode(xml_content)
|
|
26
|
+
|
|
27
|
+
case mode
|
|
28
|
+
when "arm"
|
|
29
|
+
ArmCompareReport.from_xml(xml_content)
|
|
30
|
+
when "mim"
|
|
31
|
+
MimCompareReport.from_xml(xml_content)
|
|
32
|
+
else
|
|
33
|
+
super
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Load a CompareReport from an XML file
|
|
38
|
+
#
|
|
39
|
+
# @param path [String] Path to the XML file
|
|
40
|
+
# @return [CompareReport] The loaded comparison report
|
|
41
|
+
def from_file(path)
|
|
42
|
+
from_xml(File.read(path))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# Detect XML mode from content
|
|
48
|
+
#
|
|
49
|
+
# @param xml_content [String] XML content
|
|
50
|
+
# @return [String] "arm", "mim", or "schema"
|
|
51
|
+
def detect_mode(xml_content)
|
|
52
|
+
if xml_content.include?("<arm.changes")
|
|
53
|
+
"arm"
|
|
54
|
+
elsif xml_content.include?("<mim.changes")
|
|
55
|
+
"mim"
|
|
56
|
+
else
|
|
57
|
+
"schema"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Detect XML mode from the report
|
|
63
|
+
# @return [String] "arm", "mim", or "schema"
|
|
64
|
+
def mode
|
|
65
|
+
"schema"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Eengine
|
|
5
|
+
# Represents an Eengine MIM comparison XML report
|
|
6
|
+
class MimCompareReport < Lutaml::Model::Serializable
|
|
7
|
+
attribute :modifications, ChangesSection
|
|
8
|
+
attribute :additions, ChangesSection
|
|
9
|
+
attribute :deletions, ChangesSection
|
|
10
|
+
|
|
11
|
+
xml do
|
|
12
|
+
element "mim.changes"
|
|
13
|
+
map_element "mim.modifications", to: :modifications
|
|
14
|
+
map_element "mim.additions", to: :additions
|
|
15
|
+
map_element "mim.deletions", to: :deletions
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def mode
|
|
19
|
+
"mim"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Expressir
|
|
4
|
+
module Eengine
|
|
5
|
+
# Represents a modified EXPRESS object in an Eengine comparison report
|
|
6
|
+
class ModifiedObject < Lutaml::Model::Serializable
|
|
7
|
+
attribute :type, :string
|
|
8
|
+
attribute :name, :string
|
|
9
|
+
attribute :interfaced_items, :string
|
|
10
|
+
attribute :description, :string
|
|
11
|
+
|
|
12
|
+
xml do
|
|
13
|
+
element "modified.object"
|
|
14
|
+
map_attribute "type", to: :type
|
|
15
|
+
map_attribute "name", to: :name
|
|
16
|
+
map_attribute "interfaced.items", to: :interfaced_items
|
|
17
|
+
map_element "description", to: :description
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
module Expressir
|
|
2
|
+
module Eengine
|
|
3
|
+
autoload :ModifiedObject, "#{__dir__}/eengine/modified_object"
|
|
4
|
+
autoload :ChangesSection, "#{__dir__}/eengine/changes_section"
|
|
5
|
+
autoload :CompareReport, "#{__dir__}/eengine/compare_report"
|
|
6
|
+
autoload :ArmCompareReport, "#{__dir__}/eengine/arm_compare_report"
|
|
7
|
+
autoload :MimCompareReport, "#{__dir__}/eengine/mim_compare_report"
|
|
8
|
+
end
|
|
9
|
+
end
|