tina4ruby 3.13.27 → 3.13.29

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22585d14a68f2f43593a60d1cd6f6173cd0c6103ef715f381195f8a4f006588e
4
- data.tar.gz: a89a7168c5175e862ef902b7501ffb85a1fa195298dd4d5b981f69695fa49cfb
3
+ metadata.gz: 01fb453b8f6a6ea027dc04bc3e1d56c808969f50739ca60946152030883e7fd0
4
+ data.tar.gz: b04d9e2902f61df6e37ae6eb81b95b6f60edf579739206ea97b9463a1ba5dd25
5
5
  SHA512:
6
- metadata.gz: f3cb82ae2d3b78cc1fecc97427200181298c6a4da3fbb1ce5820cce8f066621bacd04f8345ee33636ea2fc1ed0b2b8f905d48358c09d0294448edc87aab54af7
7
- data.tar.gz: e551aea110d6e9e86e44d003522145a734221da3942120c2c563df98e05b4092c66919afebeecaae01ed78ca2c533fc6b8ef6eb2a78bf4ebbf0f604c0656ba46
6
+ metadata.gz: 4c3ce7f5a22fef09964273c1645a3b1756a2359bf2d670bcc2b3c640bd8f0689a38653dd046b12c000fdc78ce9cbbb0dec386317a5d13e3cf09243c39461888f
7
+ data.tar.gz: dca9b42a7753fd2609d263867846d236e1c3e10b094f37a6030c690cadab75e3041b787e886c6feceb7dbafcb73b8bf3ba090c60fc69167e3309d1f3b79d378c
data/lib/tina4/docs.rb CHANGED
@@ -98,8 +98,7 @@ module Tina4
98
98
  # Full reflection of a single class — `nil` for unknown.
99
99
  def class_spec(fqn)
100
100
  ensure_index
101
- key = normalise_fqn(fqn)
102
- class_entry = all_entries.find { |e| e[:kind] == "class" && e[:fqn] == key }
101
+ class_entry = resolve_class(fqn)
103
102
  return nil if class_entry.nil?
104
103
 
105
104
  methods = all_entries.select do |m|
@@ -123,9 +122,10 @@ module Tina4
123
122
  # Single method spec — `nil` for unknown.
124
123
  def method_spec(class_fqn, method_name)
125
124
  ensure_index
126
- key = normalise_fqn(class_fqn)
125
+ klass = resolve_class(class_fqn)
126
+ resolved = klass ? klass[:fqn] : normalise_fqn(class_fqn)
127
127
  entry = all_entries.find do |e|
128
- e[:kind] == "method" && e[:class_fqn] == key && e[:name] == method_name.to_s
128
+ e[:kind] == "method" && e[:class_fqn] == resolved && e[:name] == method_name.to_s
129
129
  end
130
130
  entry && method_payload(entry)
131
131
  end
@@ -558,6 +558,38 @@ module Tina4
558
558
  tokens.each do |tk|
559
559
  score += 1 if !tk.empty? && doc.include?(tk)
560
560
  end
561
+
562
+ # Class-qualified queries ("Frond.add_test" / "Frond::add_test" /
563
+ # "Frond add_test"): score the owning class so the qualifier steers
564
+ # ranking instead of being dead weight.
565
+ class_fqn = (entry[:class_fqn] || entry[:class]).to_s
566
+ unless class_fqn.empty?
567
+ parent = class_fqn.split("::").last.to_s.downcase
568
+ unless parent.empty?
569
+ # Exact "Class.method" intent — normalise `.`/`::`/whitespace in the
570
+ # (already space-stripped) joined query to a single `.` separator.
571
+ q_norm = joined.gsub(/[:.]+/, ".")
572
+ if q_norm == "#{parent}.#{name}" || q_norm == "#{parent}.#{stripped}"
573
+ score += 6 # strongest signal we have
574
+ end
575
+ tokens.each do |tk|
576
+ next if tk.empty?
577
+ if tk == parent
578
+ score += 2.5
579
+ elsif parent.start_with?(tk)
580
+ score += 1
581
+ end
582
+ end
583
+ end
584
+ end
585
+
586
+ # Any token that is a whole dotted / :: segment of the fqn
587
+ # (namespace / class / method).
588
+ fqn_segs = entry[:fqn].to_s.downcase.split(/[.:#\s]+/).reject(&:empty?)
589
+ tokens.each do |tk|
590
+ score += 1 if !tk.empty? && fqn_segs.include?(tk)
591
+ end
592
+
561
593
  # Substring fallback — full joined query inside the name.
562
594
  if !joined.empty? && score.zero? && name.include?(joined)
563
595
  score += 2
@@ -632,5 +664,36 @@ module Tina4
632
664
  def normalise_fqn(fqn)
633
665
  fqn.to_s.sub(/\A::/, "")
634
666
  end
667
+
668
+ # Resolve a class entry by exact FQN, documented public path, or bare name.
669
+ #
670
+ # Callers naturally type the exact stored FQN (`Tina4::Database`), a bare
671
+ # class name (`Database`), or a longer path that nests the class name
672
+ # (`Tina4::Database::Database`). Match exactly first, then by class name
673
+ # (the last `::`/`.` segment), disambiguating by requiring the given
674
+ # segments to appear in the stored FQN (framework + shortest wins). A
675
+ # genuinely unknown name returns `nil` — no false positives.
676
+ def resolve_class(given)
677
+ classes = all_entries.select { |e| e[:kind] == "class" }
678
+ key = normalise_fqn(given)
679
+
680
+ exact = classes.find { |e| e[:fqn] == key }
681
+ return exact if exact
682
+
683
+ gsegs = key.split(/[:.]+/).reject(&:empty?)
684
+ gname = gsegs.empty? ? key : gsegs.last
685
+ cands = classes.select { |e| e[:fqn].to_s.split(/[:.]+/).last == gname }
686
+ return nil if cands.empty?
687
+ return cands.first if cands.size == 1
688
+
689
+ # Disambiguate: prefer classes whose stored FQN contains every given
690
+ # segment, then framework source, then the shortest FQN.
691
+ subset = cands.select do |e|
692
+ segs = e[:fqn].to_s.split(/[:.]+/)
693
+ gsegs.all? { |s| segs.include?(s) }
694
+ end
695
+ pool = subset.empty? ? cands : subset
696
+ pool.min_by { |e| [e[:source] == "framework" ? 0 : 1, e[:fqn].to_s.length, e[:fqn].to_s] }
697
+ end
635
698
  end
636
699
  end
data/lib/tina4/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tina4
4
- VERSION = "3.13.27"
4
+ VERSION = "3.13.29"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tina4ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.13.27
4
+ version: 3.13.29
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tina4 Team