expressir 2.3.0 → 2.3.2
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/.rubocop_todo.yml +480 -49
- data/benchmark/srl_benchmark.rb +47 -34
- data/benchmark/srl_native_benchmark.rb +20 -16
- data/benchmark/srl_ruby_benchmark.rb +14 -12
- data/expressir.gemspec +2 -2
- data/lib/expressir/changes/item_change.rb +0 -1
- data/lib/expressir/changes/mapping_change.rb +0 -1
- data/lib/expressir/changes/schema_change.rb +0 -1
- data/lib/expressir/changes/version_change.rb +0 -1
- data/lib/expressir/commands/changes_import_eengine.rb +2 -2
- data/lib/expressir/commands/validate_ascii.rb +0 -1
- data/lib/expressir/eengine/arm_compare_report.rb +0 -1
- data/lib/expressir/eengine/changes_section.rb +0 -1
- data/lib/expressir/eengine/mim_compare_report.rb +0 -1
- data/lib/expressir/eengine/modified_object.rb +0 -1
- data/lib/expressir/express/builder.rb +64 -21
- data/lib/expressir/express/builders/built_in_builder.rb +4 -2
- data/lib/expressir/express/builders/entity_decl_builder.rb +8 -4
- data/lib/expressir/express/builders/expression_builder.rb +0 -6
- data/lib/expressir/express/builders/function_decl_builder.rb +8 -8
- data/lib/expressir/express/builders/procedure_decl_builder.rb +8 -8
- data/lib/expressir/express/builders/rule_decl_builder.rb +8 -8
- data/lib/expressir/express/builders/syntax_builder.rb +2 -44
- data/lib/expressir/express/formatters/remark_formatter.rb +1 -3
- data/lib/expressir/express/parser.rb +234 -14
- data/lib/expressir/express/remark_attacher.rb +79 -169
- data/lib/expressir/express/transformer/remark_handling.rb +0 -1
- data/lib/expressir/model/declarations/schema.rb +0 -1
- data/lib/expressir/model/exp_file.rb +2 -1
- data/lib/expressir/model/model_element.rb +1 -1
- data/lib/expressir/model/repository.rb +8 -9
- data/lib/expressir/model/search_engine.rb +7 -6
- data/lib/expressir/package/builder.rb +3 -1
- data/lib/expressir/package/metadata.rb +0 -1
- data/lib/expressir/schema_manifest.rb +0 -1
- data/lib/expressir/schema_manifest_entry.rb +0 -1
- data/lib/expressir/version.rb +1 -1
- metadata +15 -15
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "set"
|
|
4
|
-
|
|
5
3
|
module Expressir
|
|
6
4
|
module Express
|
|
7
5
|
# Handles attaching remarks (comments) to model elements after parsing.
|
|
@@ -13,6 +11,17 @@ module Expressir
|
|
|
13
11
|
# 2. Proximity-based matching for simple tags
|
|
14
12
|
# 3. NOT creating spurious schema-level items for ambiguous tags
|
|
15
13
|
class RemarkAttacher
|
|
14
|
+
# Child collection attributes to walk when traversing model elements.
|
|
15
|
+
# These are the named collections on model elements (e.g., entity.attributes,
|
|
16
|
+
# schema.entities, function.parameters). Extracted to a constant to avoid
|
|
17
|
+
# duplication between calculate_children_end_line and collect_children.
|
|
18
|
+
CHILD_COLLECTION_ATTRIBUTES = %i[
|
|
19
|
+
schemas types entities functions procedures rules constants
|
|
20
|
+
attributes derived_attributes inverse_attributes
|
|
21
|
+
where_rules unique_rules informal_propositions
|
|
22
|
+
parameters variables statements items remark_items
|
|
23
|
+
].freeze
|
|
24
|
+
|
|
16
25
|
def initialize(source)
|
|
17
26
|
@source = source
|
|
18
27
|
@attached_spans = Set.new
|
|
@@ -25,8 +34,22 @@ module Expressir
|
|
|
25
34
|
def attach(model)
|
|
26
35
|
@model = model
|
|
27
36
|
remarks = extract_all_remarks
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
|
|
38
|
+
# Build nodes_with_positions ONCE for both tagged and untagged remark passes.
|
|
39
|
+
# This avoids double tree walk (381K nodes × 2 = 762K visits) which was
|
|
40
|
+
# the largest memory overhead in remark attachment (~430MB for large files).
|
|
41
|
+
nodes_with_positions = build_sorted_nodes_with_positions(model)
|
|
42
|
+
|
|
43
|
+
attach_tagged_remarks(model, remarks, nodes_with_positions)
|
|
44
|
+
attach_untagged_remarks(remarks, nodes_with_positions)
|
|
45
|
+
|
|
46
|
+
# Free expensive data structures after attachment is complete.
|
|
47
|
+
# These are only needed during the attach process.
|
|
48
|
+
@source = nil
|
|
49
|
+
@source_lines = nil
|
|
50
|
+
@scope_map = nil
|
|
51
|
+
@line_cache = nil
|
|
52
|
+
|
|
30
53
|
model
|
|
31
54
|
end
|
|
32
55
|
|
|
@@ -124,9 +147,7 @@ module Expressir
|
|
|
124
147
|
@line_cache[position] ||= @source.byteslice(0...position).count("\n") + 1
|
|
125
148
|
end
|
|
126
149
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def attach_tagged_remarks(model, remarks)
|
|
150
|
+
def attach_tagged_remarks(model, remarks, nodes_with_positions)
|
|
130
151
|
tagged = remarks.select { |r| r[:tag] }
|
|
131
152
|
return if tagged.empty?
|
|
132
153
|
|
|
@@ -136,12 +157,6 @@ module Expressir
|
|
|
136
157
|
# This is the key optimization that makes scope lookup O(1) per remark
|
|
137
158
|
@scope_map ||= build_scope_map
|
|
138
159
|
|
|
139
|
-
# Collect nodes with positions for position-based fallback
|
|
140
|
-
nodes_with_positions = []
|
|
141
|
-
collect_nodes_with_positions(model, nodes_with_positions)
|
|
142
|
-
# Use stable sort to ensure deterministic ordering across Ruby versions
|
|
143
|
-
nodes_with_positions.sort_by!.with_index { |n, i| [n[:position] || Float::INFINITY, i] }
|
|
144
|
-
|
|
145
160
|
tagged.sort_by { |r| r[:position] }.each do |remark|
|
|
146
161
|
next if @attached_spans.include?(remark[:position])
|
|
147
162
|
|
|
@@ -242,7 +257,8 @@ module Expressir
|
|
|
242
257
|
end
|
|
243
258
|
# Fall back to schema prefix
|
|
244
259
|
if target.nil?
|
|
245
|
-
target = create_implicit_remark_item(model, tag,
|
|
260
|
+
target = create_implicit_remark_item(model, tag,
|
|
261
|
+
get_schema_ids(model))
|
|
246
262
|
end
|
|
247
263
|
end
|
|
248
264
|
|
|
@@ -280,6 +296,7 @@ module Expressir
|
|
|
280
296
|
|
|
281
297
|
nil
|
|
282
298
|
end
|
|
299
|
+
|
|
283
300
|
# Done once per RemarkAttacher instance (O(file_lines)).
|
|
284
301
|
# Each find_containing_scope call then becomes O(1).
|
|
285
302
|
def build_scope_map
|
|
@@ -557,102 +574,6 @@ module Expressir
|
|
|
557
574
|
find_containing_scope_position(remark_line, nodes_with_positions)
|
|
558
575
|
end
|
|
559
576
|
|
|
560
|
-
def find_scope_by_text_search(remark_line)
|
|
561
|
-
lines = source_lines
|
|
562
|
-
return nil if remark_line < 1 || remark_line > lines.length
|
|
563
|
-
|
|
564
|
-
# Track nested scopes by searching backwards from remark_line
|
|
565
|
-
scope_stack = []
|
|
566
|
-
|
|
567
|
-
lines.each_with_index do |line, idx|
|
|
568
|
-
line_num = idx + 1
|
|
569
|
-
break if line_num > remark_line
|
|
570
|
-
|
|
571
|
-
# Check for START keywords first
|
|
572
|
-
if line =~ /^\s*SCHEMA\s+(\w+)/i
|
|
573
|
-
scope_stack << { type: :schema, name: $1, line: line_num }
|
|
574
|
-
end
|
|
575
|
-
|
|
576
|
-
if line =~ /^\s*FUNCTION\s+(\w+)/i
|
|
577
|
-
scope_stack << { type: :function, name: $1, line: line_num }
|
|
578
|
-
end
|
|
579
|
-
|
|
580
|
-
if line =~ /^\s*PROCEDURE\s+(\w+)/i
|
|
581
|
-
scope_stack << { type: :procedure, name: $1, line: line_num }
|
|
582
|
-
end
|
|
583
|
-
|
|
584
|
-
if line =~ /^\s*RULE\s+(\w+)/i
|
|
585
|
-
scope_stack << { type: :rule, name: $1, line: line_num }
|
|
586
|
-
end
|
|
587
|
-
|
|
588
|
-
if line =~ /^\s*ENTITY\s+(\w+)/i
|
|
589
|
-
scope_stack << { type: :entity, name: $1, line: line_num }
|
|
590
|
-
end
|
|
591
|
-
|
|
592
|
-
if line =~ /^\s*TYPE\s+(\w+)/i
|
|
593
|
-
scope_stack << { type: :type, name: $1, line: line_num }
|
|
594
|
-
end
|
|
595
|
-
|
|
596
|
-
# Then check for END keywords (to handle inline closures on same line)
|
|
597
|
-
if (line =~ /END_TYPE/i) && (scope_stack.last&.dig(:type) == :type)
|
|
598
|
-
scope_stack.pop
|
|
599
|
-
end
|
|
600
|
-
if (line =~ /END_FUNCTION/i) && (scope_stack.last&.dig(:type) == :function)
|
|
601
|
-
scope_stack.pop
|
|
602
|
-
end
|
|
603
|
-
if (line =~ /END_PROCEDURE/i) && (scope_stack.last&.dig(:type) == :procedure)
|
|
604
|
-
scope_stack.pop
|
|
605
|
-
end
|
|
606
|
-
if (line =~ /END_RULE/i) && (scope_stack.last&.dig(:type) == :rule)
|
|
607
|
-
scope_stack.pop
|
|
608
|
-
end
|
|
609
|
-
if (line =~ /END_ENTITY/i) && (scope_stack.last&.dig(:type) == :entity)
|
|
610
|
-
scope_stack.pop
|
|
611
|
-
end
|
|
612
|
-
if (line =~ /END_SCHEMA/i) && (scope_stack.last&.dig(:type) == :schema)
|
|
613
|
-
scope_stack.pop
|
|
614
|
-
end
|
|
615
|
-
end
|
|
616
|
-
|
|
617
|
-
# Find the innermost scope and get the corresponding model node
|
|
618
|
-
return nil if scope_stack.empty?
|
|
619
|
-
|
|
620
|
-
innermost = scope_stack.last
|
|
621
|
-
find_scope_node(innermost[:type], innermost[:name])
|
|
622
|
-
end
|
|
623
|
-
|
|
624
|
-
def find_scope_node(type, name)
|
|
625
|
-
return nil unless @model && name
|
|
626
|
-
|
|
627
|
-
@model.schemas.each do |schema|
|
|
628
|
-
# Check schema itself
|
|
629
|
-
if type == :schema && schema.id == name
|
|
630
|
-
return schema
|
|
631
|
-
end
|
|
632
|
-
|
|
633
|
-
# Check schema-level declarations
|
|
634
|
-
case type
|
|
635
|
-
when :function
|
|
636
|
-
found = schema.functions&.find { |f| f.id == name }
|
|
637
|
-
return found if found
|
|
638
|
-
when :procedure
|
|
639
|
-
found = schema.procedures&.find { |p| p.id == name }
|
|
640
|
-
return found if found
|
|
641
|
-
when :rule
|
|
642
|
-
found = schema.rules&.find { |r| r.id == name }
|
|
643
|
-
return found if found
|
|
644
|
-
when :entity
|
|
645
|
-
found = schema.entities&.find { |e| e.id == name }
|
|
646
|
-
return found if found
|
|
647
|
-
when :type
|
|
648
|
-
found = schema.types&.find { |t| t.id == name }
|
|
649
|
-
return found if found
|
|
650
|
-
end
|
|
651
|
-
end
|
|
652
|
-
|
|
653
|
-
nil
|
|
654
|
-
end
|
|
655
|
-
|
|
656
577
|
def build_scope_path(node)
|
|
657
578
|
return nil unless node
|
|
658
579
|
|
|
@@ -673,36 +594,6 @@ module Expressir
|
|
|
673
594
|
parts.empty? ? nil : parts.join(".")
|
|
674
595
|
end
|
|
675
596
|
|
|
676
|
-
def find_containing_scope_for_ip(remark_line, nodes_with_positions)
|
|
677
|
-
# First try scope map (O(1))
|
|
678
|
-
scope = find_containing_scope_by_name(remark_line)
|
|
679
|
-
if scope && supports_informal_propositions?(scope)
|
|
680
|
-
return scope
|
|
681
|
-
end
|
|
682
|
-
|
|
683
|
-
# Fallback to position-based detection
|
|
684
|
-
containing_nodes = nodes_with_positions.select do |n|
|
|
685
|
-
n[:line] && n[:end_line] && remark_line >= n[:line] && remark_line <= n[:end_line] &&
|
|
686
|
-
!repository?(n[:node]) && !cache?(n[:node])
|
|
687
|
-
end
|
|
688
|
-
|
|
689
|
-
# Find the innermost node that supports informal propositions
|
|
690
|
-
if containing_nodes.any?
|
|
691
|
-
containing_nodes.reverse_each do |n|
|
|
692
|
-
node = n[:node]
|
|
693
|
-
if supports_informal_propositions?(node)
|
|
694
|
-
return node
|
|
695
|
-
end
|
|
696
|
-
|
|
697
|
-
# Fallback to schema
|
|
698
|
-
return node if node.is_a?(Model::Declarations::Schema)
|
|
699
|
-
end
|
|
700
|
-
end
|
|
701
|
-
|
|
702
|
-
# Fallback: search for containing entity/type/rule by source text
|
|
703
|
-
find_scope_by_source_text(remark_line)
|
|
704
|
-
end
|
|
705
|
-
|
|
706
597
|
def find_scope_by_source_text(remark_line)
|
|
707
598
|
# Search backwards from remark_line for containing scope
|
|
708
599
|
lines = source_lines
|
|
@@ -908,15 +799,10 @@ module Expressir
|
|
|
908
799
|
item
|
|
909
800
|
end
|
|
910
801
|
|
|
911
|
-
def attach_untagged_remarks(
|
|
802
|
+
def attach_untagged_remarks(remarks, nodes_with_positions)
|
|
912
803
|
untagged = remarks.reject { |r| r[:tag] }
|
|
913
804
|
return unless untagged.any?
|
|
914
805
|
|
|
915
|
-
nodes_with_positions = []
|
|
916
|
-
collect_nodes_with_positions(model, nodes_with_positions)
|
|
917
|
-
# Use stable sort to preserve original order for equal keys
|
|
918
|
-
nodes_with_positions.sort_by!.with_index { |n, i| [n[:position] || Float::INFINITY, i] }
|
|
919
|
-
|
|
920
806
|
untagged.each do |remark|
|
|
921
807
|
next if @attached_spans.include?(remark[:position])
|
|
922
808
|
|
|
@@ -1021,21 +907,41 @@ module Expressir
|
|
|
1021
907
|
# The parser always provides this via Slice#offset
|
|
1022
908
|
if node.source_offset
|
|
1023
909
|
pos = node.source_offset
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
#
|
|
1028
|
-
#
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
910
|
+
# Validate offset: native parser returns 0 for leaf nodes (WhereRule)
|
|
911
|
+
# where it can't determine the actual position. These have short
|
|
912
|
+
# expression-like source ("TRUE;") that doesn't appear at file start.
|
|
913
|
+
# Container nodes (Schema, Entity, Type) have declaration-like source
|
|
914
|
+
# that either starts at position 0 legitimately or is clearly valid.
|
|
915
|
+
valid = pos.positive?
|
|
916
|
+
if !valid && pos.zero? && node.source
|
|
917
|
+
src = node.source.to_s
|
|
918
|
+
# Accept position=0 if source is a declaration keyword line
|
|
919
|
+
valid = src.start_with?("SCHEMA", "ENTITY", "TYPE", "FUNCTION",
|
|
920
|
+
"PROCEDURE", "RULE", "CONSTANT", "VARIABLE",
|
|
921
|
+
"USE", "REFERENCE", "END_SCHEMA", "END_ENTITY",
|
|
922
|
+
"END_TYPE", "END_FUNCTION", "END_PROCEDURE",
|
|
923
|
+
"END_RULE", "END_CONSTANT", "END_VARIABLE")
|
|
924
|
+
end
|
|
925
|
+
if valid
|
|
926
|
+
line = get_line_number(pos)
|
|
927
|
+
source_end_line = get_line_number(pos + node.source.length)
|
|
928
|
+
|
|
929
|
+
# For container nodes, use the maximum end_line from children
|
|
930
|
+
# This is needed because source.length only covers the declaration, not the body
|
|
931
|
+
children_end_line = calculate_children_end_line(node)
|
|
932
|
+
end_line = [source_end_line,
|
|
933
|
+
children_end_line].compact.max || source_end_line
|
|
934
|
+
|
|
935
|
+
result << {
|
|
936
|
+
node: node,
|
|
937
|
+
position: pos,
|
|
938
|
+
line: line,
|
|
939
|
+
end_line: end_line,
|
|
940
|
+
}
|
|
941
|
+
else
|
|
942
|
+
# Invalid offset — treat as unknown position
|
|
943
|
+
result << { node: node, position: nil, line: nil, end_line: nil }
|
|
944
|
+
end
|
|
1039
945
|
else
|
|
1040
946
|
# No source_offset available - should not happen if parser provides Slice
|
|
1041
947
|
result << { node: node, position: nil, line: nil, end_line: nil }
|
|
@@ -1063,10 +969,7 @@ module Expressir
|
|
|
1063
969
|
end
|
|
1064
970
|
|
|
1065
971
|
# Check specific child collections
|
|
1066
|
-
|
|
1067
|
-
attributes derived_attributes inverse_attributes
|
|
1068
|
-
where_rules unique_rules informal_propositions
|
|
1069
|
-
parameters variables statements items remark_items].each do |attr|
|
|
972
|
+
CHILD_COLLECTION_ATTRIBUTES.each do |attr|
|
|
1070
973
|
collection = safe_get_collection(node, attr)
|
|
1071
974
|
collection&.each do |child|
|
|
1072
975
|
if child.is_a?(Model::ModelElement) && child.source_offset && child.source
|
|
@@ -1085,10 +988,7 @@ module Expressir
|
|
|
1085
988
|
collect_nodes_with_positions(child, result, visited)
|
|
1086
989
|
end
|
|
1087
990
|
|
|
1088
|
-
|
|
1089
|
-
attributes derived_attributes inverse_attributes
|
|
1090
|
-
where_rules unique_rules informal_propositions
|
|
1091
|
-
parameters variables statements items remark_items].each do |attr|
|
|
991
|
+
CHILD_COLLECTION_ATTRIBUTES.each do |attr|
|
|
1092
992
|
collection = safe_get_collection(node, attr)
|
|
1093
993
|
collection&.each do |item|
|
|
1094
994
|
collect_nodes_with_positions(item, result, visited)
|
|
@@ -1096,6 +996,16 @@ module Expressir
|
|
|
1096
996
|
end
|
|
1097
997
|
end
|
|
1098
998
|
|
|
999
|
+
# Build sorted nodes_with_positions ONCE for both tagged and untagged remark passes.
|
|
1000
|
+
# This merges the two separate tree walks into one, cutting node visits in half.
|
|
1001
|
+
def build_sorted_nodes_with_positions(model)
|
|
1002
|
+
nodes_with_positions = []
|
|
1003
|
+
collect_nodes_with_positions(model, nodes_with_positions)
|
|
1004
|
+
# Stable sort: nil positions last, ties broken by insertion order
|
|
1005
|
+
nodes_with_positions.sort_by!.with_index { |n, i| [n[:position] || Float::INFINITY, i] }
|
|
1006
|
+
nodes_with_positions
|
|
1007
|
+
end
|
|
1008
|
+
|
|
1099
1009
|
def find_nearest_node(remark, nodes)
|
|
1100
1010
|
remark_line = remark[:line]
|
|
1101
1011
|
|
|
@@ -14,7 +14,8 @@ module Expressir
|
|
|
14
14
|
include ScopeContainer
|
|
15
15
|
|
|
16
16
|
attribute :path, :string
|
|
17
|
-
attribute :schemas, Declarations::Schema, collection: true,
|
|
17
|
+
attribute :schemas, Declarations::Schema, collection: true,
|
|
18
|
+
initialize_empty: true
|
|
18
19
|
attribute :_class, :string, default: -> { self.class.name }
|
|
19
20
|
|
|
20
21
|
key_value do
|
|
@@ -32,8 +32,8 @@ module Expressir
|
|
|
32
32
|
map "files", to: :files
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
def initialize(
|
|
36
|
-
super(
|
|
35
|
+
def initialize(*, base_dir: nil, schemas: nil, **)
|
|
36
|
+
super(*, **)
|
|
37
37
|
@base_dir = base_dir
|
|
38
38
|
@entity_index = nil
|
|
39
39
|
@type_index = nil
|
|
@@ -41,9 +41,7 @@ module Expressir
|
|
|
41
41
|
@_schemas = []
|
|
42
42
|
|
|
43
43
|
# Support direct schemas initialization
|
|
44
|
-
|
|
45
|
-
schemas.each { |schema| @_schemas << schema }
|
|
46
|
-
end
|
|
44
|
+
schemas&.each { |schema| @_schemas << schema }
|
|
47
45
|
end
|
|
48
46
|
|
|
49
47
|
# Get all schemas (from both files and direct storage)
|
|
@@ -63,6 +61,7 @@ module Expressir
|
|
|
63
61
|
# @param schema [Declarations::Schema] Schema to add
|
|
64
62
|
def add_schema(schema)
|
|
65
63
|
return unless schema
|
|
64
|
+
|
|
66
65
|
@_schemas << schema
|
|
67
66
|
end
|
|
68
67
|
|
|
@@ -342,16 +341,16 @@ module Expressir
|
|
|
342
341
|
# @param format [Symbol] Output format
|
|
343
342
|
# @yield [item] Block to convert item to hash
|
|
344
343
|
# @return [Array, String] Formatted output
|
|
345
|
-
def format_output(items, format, &
|
|
344
|
+
def format_output(items, format, &)
|
|
346
345
|
case format
|
|
347
346
|
when :hash
|
|
348
|
-
items.map(&
|
|
347
|
+
items.map(&)
|
|
349
348
|
when :json
|
|
350
349
|
require "json"
|
|
351
|
-
items.map(&
|
|
350
|
+
items.map(&).to_json
|
|
352
351
|
when :yaml
|
|
353
352
|
require "yaml"
|
|
354
|
-
items.map(&
|
|
353
|
+
items.map(&).to_yaml
|
|
355
354
|
else
|
|
356
355
|
items
|
|
357
356
|
end
|
|
@@ -84,10 +84,10 @@ module Expressir
|
|
|
84
84
|
# @param max_depth [Integer] Maximum path depth (1=schema, 2=entity, 3=attribute)
|
|
85
85
|
# @param options [Hash] Additional search options
|
|
86
86
|
# @return [Array<Hash>] Filtered results
|
|
87
|
-
def search_with_depth(pattern:, max_depth:, **
|
|
87
|
+
def search_with_depth(pattern:, max_depth:, **)
|
|
88
88
|
return [] if max_depth <= 0
|
|
89
89
|
|
|
90
|
-
results = search(pattern: pattern, **
|
|
90
|
+
results = search(pattern: pattern, **)
|
|
91
91
|
filter_by_depth(results, max_depth)
|
|
92
92
|
end
|
|
93
93
|
|
|
@@ -97,8 +97,8 @@ module Expressir
|
|
|
97
97
|
# @param boost_prefix [Integer] Score boost for prefix matches
|
|
98
98
|
# @param options [Hash] Additional search options
|
|
99
99
|
# @return [Array<Hash>] Ranked results with :relevance_score
|
|
100
|
-
def search_ranked(pattern:, boost_exact: 10, boost_prefix: 5, **
|
|
101
|
-
results = search(pattern: pattern, **
|
|
100
|
+
def search_ranked(pattern:, boost_exact: 10, boost_prefix: 5, **)
|
|
101
|
+
results = search(pattern: pattern, **)
|
|
102
102
|
rank_results(results, pattern, boost_exact, boost_prefix)
|
|
103
103
|
end
|
|
104
104
|
|
|
@@ -108,8 +108,8 @@ module Expressir
|
|
|
108
108
|
# @param ranked [Boolean] Enable relevance ranking
|
|
109
109
|
# @param options [Hash] Additional filters and search options
|
|
110
110
|
# @return [Array<Hash>] Filtered and optionally ranked results
|
|
111
|
-
def search_advanced(pattern:, max_depth: nil, ranked: false, **
|
|
112
|
-
results = search(pattern: pattern, **
|
|
111
|
+
def search_advanced(pattern:, max_depth: nil, ranked: false, **)
|
|
112
|
+
results = search(pattern: pattern, **)
|
|
113
113
|
|
|
114
114
|
results = filter_by_depth(results, max_depth) if max_depth
|
|
115
115
|
results = rank_results(results, pattern, 10, 5) if ranked
|
|
@@ -485,6 +485,7 @@ module Expressir
|
|
|
485
485
|
current = element
|
|
486
486
|
while current
|
|
487
487
|
return current if current.is_a?(Declarations::Schema)
|
|
488
|
+
|
|
488
489
|
current = current.parent
|
|
489
490
|
end
|
|
490
491
|
rescue StandardError
|
|
@@ -152,7 +152,9 @@ module Expressir
|
|
|
152
152
|
|
|
153
153
|
# Get schemas that are not already in files
|
|
154
154
|
file_schema_ids = normalized.files.flat_map(&:schemas).compact.map(&:id)
|
|
155
|
-
direct_schemas = repository.schemas.reject
|
|
155
|
+
direct_schemas = repository.schemas.reject do |s|
|
|
156
|
+
file_schema_ids.include?(s.id)
|
|
157
|
+
end
|
|
156
158
|
|
|
157
159
|
# Create an ExpFile for direct schemas
|
|
158
160
|
if direct_schemas.any?
|
data/lib/expressir/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: expressir
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.3.
|
|
4
|
+
version: 2.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-03
|
|
11
|
+
date: 2026-04-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|
|
@@ -109,7 +109,7 @@ dependencies:
|
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '0'
|
|
111
111
|
- !ruby/object:Gem::Dependency
|
|
112
|
-
name:
|
|
112
|
+
name: nokogiri
|
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
|
114
114
|
requirements:
|
|
115
115
|
- - ">="
|
|
@@ -123,39 +123,39 @@ dependencies:
|
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
124
|
version: '0'
|
|
125
125
|
- !ruby/object:Gem::Dependency
|
|
126
|
-
name:
|
|
126
|
+
name: paint
|
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
|
128
128
|
requirements:
|
|
129
|
-
- - "~>"
|
|
130
|
-
- !ruby/object:Gem::Version
|
|
131
|
-
version: 1.3.7
|
|
132
129
|
- - ">="
|
|
133
130
|
- !ruby/object:Gem::Version
|
|
134
|
-
version:
|
|
131
|
+
version: '0'
|
|
135
132
|
type: :runtime
|
|
136
133
|
prerelease: false
|
|
137
134
|
version_requirements: !ruby/object:Gem::Requirement
|
|
138
135
|
requirements:
|
|
139
|
-
- - "~>"
|
|
140
|
-
- !ruby/object:Gem::Version
|
|
141
|
-
version: 1.3.7
|
|
142
136
|
- - ">="
|
|
143
137
|
- !ruby/object:Gem::Version
|
|
144
|
-
version:
|
|
138
|
+
version: '0'
|
|
145
139
|
- !ruby/object:Gem::Dependency
|
|
146
|
-
name:
|
|
140
|
+
name: parsanol
|
|
147
141
|
requirement: !ruby/object:Gem::Requirement
|
|
148
142
|
requirements:
|
|
143
|
+
- - "~>"
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: 1.3.9
|
|
149
146
|
- - ">="
|
|
150
147
|
- !ruby/object:Gem::Version
|
|
151
|
-
version:
|
|
148
|
+
version: 1.3.9
|
|
152
149
|
type: :runtime
|
|
153
150
|
prerelease: false
|
|
154
151
|
version_requirements: !ruby/object:Gem::Requirement
|
|
155
152
|
requirements:
|
|
153
|
+
- - "~>"
|
|
154
|
+
- !ruby/object:Gem::Version
|
|
155
|
+
version: 1.3.9
|
|
156
156
|
- - ">="
|
|
157
157
|
- !ruby/object:Gem::Version
|
|
158
|
-
version:
|
|
158
|
+
version: 1.3.9
|
|
159
159
|
- !ruby/object:Gem::Dependency
|
|
160
160
|
name: ruby-progressbar
|
|
161
161
|
requirement: !ruby/object:Gem::Requirement
|